local Entity = import(".Entity") local Effect = import(".Effect")

local Actor = class("Actor",Entity)

local DBAniEventType = require("dragonbones.AnimationEventType")
local Armature = require("app.public.avatar.Armature")
local SequencePlayer = import(".SequencePlayer")
local PlayerStatusBar = require("app.battleV3.ui.objs.PlayerStatusBar")
local EntityEffectController = import(".EntityEffectController")
local BuffModel = import(".models.BuffModel")
local LocationConfig = import(".BattleLocation")
local SkillEvent     = require("app.battleV3.ui.objs.SkillEvent")
local DamageFloatView = import(".views.DamageFloatView")
local AbsorbFloatView = import(".views.AbsorbFloatView")
local ImmunityFloatView = import(".views.ImmunityFloatView")
local InterrupedFloatView = import(".views.InterrupedFloatView")
local MissFloatView = import(".views.MissFloatView")
local SkillNameFloatView = import(".views.SkillNameFloatView")
local BuffNameFloatView = import(".views.BuffNameFloatView")
local DebuffNameFloatView = import(".views.DebuffNameFloatView")

local CCNode_getChildren = cc.Node.getChildren
local CCNode_getChildrenCount = cc.Node.getChildrenCount
local CCNode_getParent = cc.Node.getParent
local CCNode_getScale = cc.Node.getScale
local CCNode_getScaleX = cc.Node.getScaleX
local CCNode_getScaleY = cc.Node.getScaleY
local CCNode_setScaleX = cc.Node.setScaleX
local CCNode_setScaleY = cc.Node.setScaleY

local CCNode_setPositionX = cc.Node.setPositionX
local CCNode_setPositionY = cc.Node.setPositionY
local CCNode_setVisible = cc.Node.setVisible
local CCNode_toLocalPosition = cc.Node.toLocalPosition
local CCNode_isVisible = cc.Node.isVisible

local Armature_getBoneWorldPosition = db.CCArmatureDisplay.getBoneWorldPosition
local Armature_setFBOOpacity = db.CCArmatureDisplay.setFBOOpacity
local Armature_isPlaying = Armature.isPlaying

local Enum_SkillScaleStatus_noScale = Enums.SkillScaleStatus.noScale
local Enum_SkillScaleStatus_castScale = Enums.SkillScaleStatus.castScale
local Enum_SkillScaleStatus_scaleToNormal = Enums.SkillScaleStatus.scaleToNormal
local Enum_CommonActionTag_BattleArmatureBuffScale = Enums.CommonActionTag.BattleArmatureBuffScale

local Enum_BattleActorType_self = Enums.BattleActorType.self
local Enum_BattleActorType_teammate = Enums.BattleActorType.teammate
local Enum_BattleActorType_enemy = Enums.BattleActorType.enemy


local math_abs = math.abs
local string_len = string.len

local ZOrderList =
{
    DB = 0,
    StateBar = 1 ,
    NickName = 2,
    SelectMark = -1,
    FocusTarget = -1,
    SelectMarkArrow = 3,
    FloatEffect = 4,
    SelectEffect = -1,
    SelfEffect = -1,
    TouchEndEffect = -1,
    DeadEffect = 5,
    ReleaseSkillEffect = 6,
    TargetedEffect = 7,
    ReviveEffect = 8,
}

local Skill_id = battle.Skill.id
local Skill_applyTime = battle.Skill.applyTime
local Skill_cfg = battle.Skill.cfg
local Skill_getMasterSkillLv = battle.Skill.getMasterSkillLv
local Skill_getAniIndex = battle.Skill.getAniIndex
local Skill_duringReleaseEnd = battle.Skill.duringReleaseEnd
local Skill_getNoTargetShake = battle.Skill.getNoTargetShake
local Skill_isChantUseAttackSpeed = battle.Skill.isChantUseAttackSpeed
local Skill_getAttackSpeed = battle.Skill.getAttackSpeed

local SkillConfig_getReleaseAnim = battle.SkillConfig.getReleaseAnim
local SkillConfig_getChantAnim = battle.SkillConfig.getChantAnim
local SkillConfig_getTrackAnim = battle.SkillConfig.getTrackAnim

local Unit_getEnterHurtTime = battle.Unit.getEnterHurtTime
local Unit_getBuffsLen = battle.Unit.getBuffsLen
local Unit_getFirstBuff = battle.Unit.getFirstBuff
local Unit_getNextBuffById = battle.Unit.getNextBuffById
local Unit_isManualMoving = battle.Unit.isManualMoving

local Entity_getId = battle.Entity.getId
local Entity_lifeRemain = battle.Entity.lifeRemain
local Buff_totalTime = battle.Buff.duration
local Buff_layerCount = battle.Buff.layerCount
local Buff_createdTime = battle.Buff.createdTime

local HURT_TOLERANCE = 100
local FALL_TOLERANCE = 100

Actor.onStateChanged = "onStateChanged"
Actor.Event_onDeadEnd = "Event_onDeadEnd"
Actor.Event_onReleaseShake = "Event_onReleaseShake"
Actor.Event_onIconChanged = "Event_onIconChanged"
Actor.Event_onClearBuffViews = "Event_onClearBuffViews"
Actor.Event_onStealthBegin = "Event_onStealthBegin"
Actor.Event_onScreenBlink = "Event_onScreenBlink"
Actor.Event_onShowDeadTips = "Event_onShowDeadTips"


----------------------------------buff--shader--------------
local EffectPriority = {}
EffectPriority[Enums.BuffEffects.Sheep]=1  --变羊
EffectPriority[Enums.BuffEffects.Frozen]=2 --冰冻
EffectPriority[Enums.BuffEffects.Stone]=3  --石化
EffectPriority[Enums.BuffEffects.Stun]=4   --晕眩
EffectPriority[Enums.BuffEffects.Fall]=5  --击飞
EffectPriority[Enums.BuffEffects.Poison]=6 --中毒
EffectPriority[Enums.BuffEffects.Sneak]=7  --潜行
EffectPriority[Enums.BuffEffects.Cold]=8  --寒冷
EffectPriority[Enums.BuffEffects.Red]=9  --变红
EffectPriority[Enums.BuffEffects.Purple]=10  --变紫 暗影斗篷/暗影形态

local TOP_STATUSBAR_ZORDER = 10

local defaultIdleAnimationName = "idle"
local defaultHurtAnimationName = "hurt"
local defaultFallAnimationName = "fall"

function Actor:ctor(params)
    Actor.super.ctor(self)
    self.dir = params.dir or 1
    self.initDir = self.dir
    self.idleAni = defaultIdleAnimationName
    self.hurtAni = defaultHurtAnimationName
    self.nextAni = nil
    self.aniPrefix = ""
    self.effectEmitters = {}
    self.chantEffectEmitters = {}
    self.sfxList = {}
    self.buffIndex = 1
    self.buffDict = {}
    self.effectsFollowDir = {}
    self.buffIconDict={}
    self.height = 0
    self.baseScale = 1
    self.effectScale = 1
    self.hpPercent = 1

    self.buffEffectExScale = 1

    self.buffUpdateIndex = 0

    self.isActionPause = false

    local armature = params.armature
    self:setArmature(armature)
    self.originArmature = armature
    self.effectController = EntityEffectController.new(self)

    self.bubbleSequnce = nil

    self.bIsEnemy = false

    self._playerNode = nil

    self.floatTextPosXIndex = nil

    self.skillScaleStatus = Enums.SkillScaleStatus.noScale

    self.actorType = Enum_BattleActorType_enemy

    self.name = "missing"

    --线的index，从1开始
    self.mLineIndex = 1

    --颜色index
    self.levelColorIndex = Enums.LevelColorIndex.normal

    self._state = Enums.CharacterState.idle

    self.isWarned = false

    self.mIsShouldRemove = false

    self._currentPositionX = 0
    self._targetX = 0
    self.moveSpeed = 0

    self.markId = Enums.TeamMarkList.NONE

    self.isShowMana = true

    self.selectSize = 100
    self.selectExcursion = 0

    self.animTimeScale = 1.0

    self.currentBuffScale = 1.0
    self.layerScale = 1.0 --在层上的缩放
    -- self.isInFrontLayer = nil --表示没有初始化，此处不要设置为false true
    self.inLayerIndex = nil -- 表示没有初始化，此处不要设置为false true

    self.followDirItems = {}

    self.bHero = params.bHero

    --头顶绑定点的世界坐标缓存，每帧更新一次
    self._pointPosX ,self._pointPosY = 0,0
    self._pointPosDirty = true
    self.bEnableOutline = UD.setting:isShowBattleOutline()
    local handle = EM:on("onSettingShowBattleOutline", function(name, isShow)
        self:setOutline(isShow)
    end)
    BattleUIEvent:addEmHandle(handle)

end

function Actor:clearPlayerNode()
    local playerNode = self._playerNode
    if playerNode and not tolua.isnull(playerNode) then
        playerNode:clearEvent()
        playerNode:clearHideEffect()
        if playerNode:getParent() then
            playerNode:removeFromParent(true)
        else
            playerNode:release()
        end
        self._playerNode = nil
    end
end

function Actor:clear()
    self:clearPlayerNode()

    if self._statusBar then
        self._statusBar:clearHideEffect()
        self._statusBar:free()
        self._statusBar = nil
    end
end

function Actor:hideState()
    if self._statusBar then
        CCNode_setVisible(self._statusBar.root, false)
    end

    if self._skillEvent then
        CCNode_setVisible(self._skillEvent.root, false)
    end

    if self.mIMBubble then
        CCNode_setVisible(self.mIMBubble, false)
    end
end

function Actor:setBubbleLayer(layer)
    self.bubbleLayer = layer
end

function Actor:setWarnningLayer(layer)
    self.warningLayer = layer
end

function Actor:setStatebarLayer(layer)
    self.statebarLayer = layer
end

function Actor:createFloatEffectPlayer()
    self.floatEffectPlayer = SequencePlayer.create()
    return self.floatEffectPlayer
end

function Actor:setBaseScale(s)
    self.baseScale = s
end

function Actor:getBaseScale()
    return self.baseScale
end

function Actor:getEffectScale()
    return self.effectScale
end

function Actor:setScale(s)
    local armature = self._armature

    local finalSX , finalSY = self:getFinalScale(s)
    CCNode_setScaleX(armature,finalSX)
    CCNode_setScaleY(armature,finalSY)

    local box = self:getBoundingBox()
    self.initArmatureX = box.x
    self.initArmatureWidth = box.width
end

function Actor:getFinalScale(s)
    local finalS = s * self:getBaseScale()*self.originScale
    return finalS*-self.dir,finalS
end

function Actor:getLeftRightPos()
    local pos = self:getPositionX()
    local leftPos = pos + (self.initArmatureX or 0)
    local rightPos = leftPos + (self.initArmatureWidth or 0)
    return leftPos,rightPos
end

function Actor:getScale()
    return self._armature:getScaleY()
end

function Actor:setHeight(v)
    self.height = v
    if self._armature then
        self._armature:setPositionY(self.height * self:getScale())
    end
end

function Actor:setInitY(y)
   self.mInitY = y + Constant.BattleFirstLineSpaceY
end

function Actor:setLine(lineIndex)
    self.mLineIndex = lineIndex
end

function Actor:getLine()
    return self.mLineIndex
end

function Actor:isSummon()
    return self.isSummonEntity
end

function Actor:isRefresh()
    return self.isRefreshEntity
end

-- function Actor:getFirstPhaseY(lineIndex)
--     local firstPhaseStepY = 15
--     return (self.mInitY - firstPhaseStepY) + (lineIndex - 1)*firstPhaseStepY
-- end

function Actor:getSpecialHPMax()
    return self.specialHpMax or 0
end

function Actor:getPosYByLine()
    -- local firstPhaseLine = 2
    -- if self.mLineIndex <= firstPhaseLine then
    --     --1 2两条线
    --     --1 在基准线下7像素，2在基准线上
    --     return self:getFirstPhaseY(self.mLineIndex)
    -- else
    --     --3 4 5...线
    --     local firstPhaseMaxY = self:getFirstPhaseY(firstPhaseLine)
    --     local secondPhaseStepY = 15
    --     return firstPhaseMaxY + (self.mLineIndex - firstPhaseLine)*secondPhaseStepY
    -- end

    local y = 0
    local listNum = #Constant.BattleLinesSpaceY
    if self.mLineIndex > 1 then
        for i=1,(self.mLineIndex - 1) do
            if i <= listNum then
                y = y + Constant.BattleLinesSpaceY[i]
            else
                y = y + Constant.BattleLinesSpaceY[listNum]
            end
        end
    end
    return y
end

function Actor:isLeft()
    --dir为1面朝右，图像在左侧
    return self.dir == 1
end


------------------------------------new--------------------------------------
function Actor:perform(state, extra)
    if self._state == state then
        self:handle("stay",extra)
    else
        -- self._extra = extra
        self:transition(state,extra)
    end
    self:performEnd()
end

function Actor:performEnd()
    -- print("performEnd id:",self:getId(),self._prevSkillId,self._skillId)
    if self._prevSkillId ~= self._skillId then
        if self._skillId == Constant.BattleScreenBlinkSkillId1 or self._skillId == Constant.BattleScreenBlinkSkillId2 then
            -- print("performEnd startScreenBlink:",self._prevSkillId,self._skillId)
            self:startScreenBlink()
        elseif self._prevSkillId == Constant.BattleScreenBlinkSkillId1 or self._prevSkillId == Constant.BattleScreenBlinkSkillId2 then
            -- print("performEnd stopScreenBlink:",self._prevSkillId,self._skillId)
            self:stopScreenBlink()
        end
    end

    self._prevSkillId = self._skillId
end

function Actor:handle(event, extra)
    self:handleStateEvent(self._state, event, extra)
end

function Actor:transition(state,extra)
    local oldState = self._state
    self:handleStateEvent(oldState, "_onExit", extra)
    self._state = state
    self:handleStateEvent(self._state, "_onEnter", extra)
    self:dispatchEvent(Actor.onStateChanged,self,oldState,state, extra)

    if state == Enums.CharacterState.dead then
        --如果死亡 对话消失
        if self.bubbleRoot then
            self.bubbleRoot:removeAllChildren()
        end

        --如果死亡 目标锁定解除
        self:setCurrentPlayerTargetFlag(false)
        if self._statusBar then
            self._statusBar:showBuff(false,nil)
            self._statusBar:clearHideEffect()
        end
        if self.coreBuff then
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_COREBONUS,self.id,false)
        end
    end
end

function Actor:hasBuffEffect(buffEffects, buffEffect)
    for k,v in pairs(buffEffects) do
        if v == buffEffect then
            return true
        end
    end
    return false
end

function Actor:isWeakRestricted(buffEffects)
    for k,v in pairs(buffEffects) do
        if v == Enums.BuffEffectsLogic.BE_Stune
          or v == Enums.BuffEffectsLogic.BE_HitRecover then
          -- or v == Enums.BuffEffectsLogic.BE_SuperStune then
            return true
        end
    end
    return false
end

function Actor:resumeAni()
    if self.sheepArmature then
        if self.sheepArmature:isPauseAni() then
            self.sheepArmature:resumeAni()
        end
    end
    if self.originArmature then
        if self.originArmature:isPauseAni() then
            self.originArmature:resumeAni()
        end
    end
end

function Actor:pauseAni()
    if self.sheepArmature then
        self.sheepArmature:pauseAni()
    end
    if self.originArmature then
        self.originArmature:pauseAni()
    end
end

function Actor:setSkillAnimTimeScale()
    if self._skill then
        self.animTimeScale = Skill_getAttackSpeed(self._skill)/10000
        self:setTimeScale(self.animTimeScale)
    end
end

function Actor:resetAnimTimeScale()
    self.animTimeScale = 1.0
    self:setTimeScale(self.animTimeScale)
end

function Actor:getChangeRes(sEffect)
    for k,buff in pairs(self.buffIconDict) do
        if buff.sEffect == sEffect then
            return buff.changeRes
        end
    end
    return nil
end

function Actor:startScreenBlink()
    self:dispatchEvent(Actor.Event_onScreenBlink, true)
end

function Actor:stopScreenBlink()
    self:dispatchEvent(Actor.Event_onScreenBlink, false)
end

function Actor:handleStateEvent(state,event,extra)
    if state == Enums.CharacterState.idle then
        if event == "_onEnter" then
            self:resumeAni()
            self:idle()
        elseif event == "_onExit" then
            self:stop()
        elseif event == "stay" then

        end
    elseif state == Enums.CharacterState.hurt then
        if event == "_onEnter" then
            self._enterHurtTime = Unit_getEnterHurtTime(extra)
            self:hurt(true)
        elseif event == "_onExit" then
            self._enterHurtTime = nil
        elseif event == "stay" then
            if extra then
                local oldEnterHurtTime = self._enterHurtTime
                self._enterHurtTime = Unit_getEnterHurtTime(extra)
                --print("====actor id:",self:getId(),"self._enterHurtTime:", self._enterHurtTime,"oldEnterHurtTime:",oldEnterHurtTime)
                if oldEnterHurtTime ~= self._enterHurtTime then
                    self:hurt(false)
                end
            end
        end
    elseif state == Enums.CharacterState.restricted then
        if event == "_onEnter" or event == "stay" then
            local buffEffects = extra.buffEffects
            if (not self:isSheep()) and self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Sheep) then
                --如果变羊
                local changeRes = self:getChangeRes(Enums.BuffEffectsLogic.BE_Sheep)
                if changeRes then
                    self:turnSheep(true,changeRes)
                end
            elseif self:isSheep() and (not self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Sheep)) then
                self:turnSheep(false)
            end

            local t = extra.t
            local fallTime = extra.fallTime
            if fallTime and fallTime > 0 and (fallTime ~= self.fallTime) and (t - fallTime < FALL_TOLERANCE) then
                self:resumeAni()
                self:fall()
                self.fallTime = fallTime
            elseif (not self:playingFall()) then
                if self:isWeakRestricted(buffEffects) then
                    self:resumeAni()
                    self:weak()
                elseif self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Frozen)
                  or self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Stone) then
                    self:pauseAni()
                elseif self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Fear) then
                    self:resumeAni()
                    self:move()
                elseif self:hasBuffEffect(buffEffects, Enums.BuffEffectsLogic.BE_Banish) then
                    local entity = extra.entity
                    if Unit_isManualMoving(entity) then
                        self:move()
                    else
                        self:idle()
                    end
                else
                    self:resumeAni()
                    self:idle()
                end
            end
        elseif event == "_onExit" then
            self:resumeAni()
            if self:isSheep() then
                self:turnSheep(false)
            end
            self.fallTime = nil
        end
    elseif state == Enums.CharacterState.move then
        if event == "_onEnter" then
            self:move()
        elseif event == "_onExit" then
        elseif event == "stay" then
            -- self:move()
        end
    elseif state == Enums.CharacterState.dead then
        if event == "_onEnter" then
            self:dead()
        elseif event == "_onExit" then
            --复活
            self:revive()
        elseif event == "stay" then
        end
    elseif state == Enums.CharacterState.skill then
        if event == "_onEnter" then
            self._skill = extra
            self._skillId = Skill_id(extra) --extra:id()--可能是subskill，subskill可能被删掉，所以通过skillId来辅助记录
            self._skillApplyTime = Skill_applyTime(extra)
            local skillConfig = Skill_cfg(self._skill) --self._skill:cfg()
            -- if not skillConfig:isBasicAttack() then
            --     self:playSkillNameEffect(L(self._skill:name())) --todo，在释放点播放效果
            -- end
            -- print("========anim count:",skillConfig:getAnimationCount())
            local index = Skill_getAniIndex(self._skill) --self._skill:getAniIndex()
            local skillLv = Skill_getMasterSkillLv(self._skill)
            -- self:setSelectStance(self._skill:name())
            -- self:skill(self._skill:name()
            self:skill(SkillConfig_getReleaseAnim(skillConfig, skillLv, index), true)
            self:setSkillAnimTimeScale()

            self._skillInReleaseEnd = Skill_duringReleaseEnd(extra)

            if self._skillInReleaseEnd then
                --print("=====_onEnter=====self._skillInReleaseEnd")
                if self:isCanPlayShake() then
                    self:dispatchEvent(Actor.Event_onReleaseShake,Skill_getNoTargetShake(extra))
                end
            end
        elseif event == "_onExit" then
            self._skill = nil
            self._skillId = nil
            self._skillApplyTime = nil
            self:resetAnimTimeScale()
        elseif event == "stay" then
            if extra then
                local skillId = self._skillId
                local skillApplyTime = self._skillApplyTime
                local extraSkillId = Skill_id(extra) --extra:id()
                local extraSkillApplyTime = Skill_applyTime(extra)
                if skillId ~= extraSkillId or skillApplyTime ~= extraSkillApplyTime then
                    -- if extra:id() == 42061701 then
                    --     print("stay skill name:",extra:name())
                    -- end

                    self._skill = extra
                    self._skillId = extraSkillId
                    self._skillApplyTime = extraSkillApplyTime
                    local skillConfig = Skill_cfg(self._skill) --self._skill:cfg()
                    local index = Skill_getAniIndex(self._skill) --self._skill:getAniIndex()
                    local skillLv = Skill_getMasterSkillLv(self._skill)
                    -- self:skill(self._skill:name())
                    self:skill(SkillConfig_getReleaseAnim(skillConfig, skillLv, index), false)
                end

                self._skill = extra -- skill会被clone上一帧记录的skill可能已经被释放掉了
                local oldSkillInReleaseEnd = self._skillInReleaseEnd
                self._skillInReleaseEnd = Skill_duringReleaseEnd(extra)
                if oldSkillInReleaseEnd ~= self._skillInReleaseEnd and self._skillInReleaseEnd then
                    --print("======stay====self._skillInReleaseEnd")
                    if self:isCanPlayShake() then
                        self:dispatchEvent(Actor.Event_onReleaseShake,Skill_getNoTargetShake(extra))
                    end
                end
                self:setSkillAnimTimeScale()
            end
        end
    elseif state == Enums.CharacterState.chant then
        if event == "_onEnter" then
            self._skill = extra
            self._skillId = Skill_id(extra) --extra:id()--可能是subskill，subskill可能被删掉，所以通过skillId来辅助记录
            local skillConfig = Skill_cfg(self._skill) --self._skill:cfg()
            local index = Skill_getAniIndex(self._skill) --self._skill:getAniIndex()
            local skillLv = Skill_getMasterSkillLv(self._skill)
            -- self:setSelectStance(self._skill:name())
            -- self:chant(self._skill:name())
            self:chant(SkillConfig_getChantAnim(skillConfig, skillLv, index) --[[skillConfig:getChantAnim(index)]])
            if Skill_isChantUseAttackSpeed(self._skill) then
                self:setSkillAnimTimeScale()
            end
        elseif event == "_onExit" then
            self._skill = nil
            self._skillId = nil
            self:resetAnimTimeScale()
        elseif event == "stay" then
            --NOTE: we way get a different extra because of entering chanting phase of sub skill
            if extra then
                local skillId = self._skillId
                local extraSkillId = Skill_id(extra) --extra:id()
                if skillId ~= extraSkillId then
                    self._skill = extra
                    self._skillId = extraSkillId
                    local skillConfig = Skill_cfg(self._skill) --self._skill:cfg()
                    local index = Skill_getAniIndex(self._skill) --self._skill:getAniIndex()
                    local skillLv = Skill_getMasterSkillLv(self._skill)
                    -- self:chant(self._skill:name())
                    self:chant(SkillConfig_getChantAnim(skillConfig, skillLv, index) --[[skillConfig:getChantAnim(index)]])
                    if Skill_isChantUseAttackSpeed(self._skill) then
                        self:setSkillAnimTimeScale()
                    end
                end
                self._skill = extra -- skill会被clone上一帧记录的skill可能已经被释放掉了
            end
        end
    elseif state == Enums.CharacterState.track then
        if event == "_onEnter" then
            self._skill = extra
            self._skillId = Skill_id(extra) --extra:id()--可能是subskill，subskill可能被删掉，所以通过skillId来辅助记录
            local skillConfig = Skill_cfg(self._skill)
            self:track(SkillConfig_getTrackAnim(skillConfig))
        elseif event == "_onExit" then
            self._skill = nil
            self._skillId = nil
        elseif event == "stay" then
            --NOTE: we way get a different extra because of entering chanting phase of sub skill
            if extra then
                local skillId = self._skillId
                local extraSkillId = Skill_id(extra) --extra:id()
                if skillId ~= extraSkillId then
                    self._skill = extra
                    self._skillId = extraSkillId
                    local skillConfig = Skill_cfg(self._skill)
                    self:track(SkillConfig_getTrackAnim(skillConfig))
                end
                self._skill = extra -- skill会被clone上一帧记录的skill可能已经被释放掉了
            end
        end
    elseif state == Enums.CharacterState.channel then
        --subskill处理引导的过程，此处待删
        -- if event == "_onEnter" then
        --     -- print("------------Enums.CharacterState.channel---------")
        --     self._skill = extra
        --     local skillConfig = self._skill:cfg()
        --     self:setSelectStance(self._skill:name())
        --     self:channel(self._skill:name())
        -- elseif event == "_onExit" then
        --     self._skill = nil
        -- elseif event == "stay" then
        --     self:channel(self._skill:name())
        -- end
    end
end

-- function Actor:processedHurt(t,hurtT)
--     if hurtT and hurtT > 0 then
--         if (t - hurtT < HURT_TOLERANCE) then
--             -- self:showFlashHurtEffect()
--         end
--         if (t - hurtT < Constant.BattleHurtMoveTime) then
--             self:hurtshake(t - hurtT)
--         end
--     end
-- end

function Actor:isDead()
    return self._state == Enums.CharacterState.dead
end

function Actor:stop(name)
    if not self._armature then
        return
    end
    if not name then
      self._armature:stop()
      return
    end
    if (not self._armature:isPlaying()) or (not self._armature:isPlaying(name)) then
      return
    end
    self._armature:stop()
end

function Actor:hurt(isCheckPlaying)
    self:once(self.hurtAni, nil, not isCheckPlaying)
end

function Actor:fall()
    self:once(defaultFallAnimationName)
end

-- function Actor:hurtshake(durTime)
--     local params = LocationConfig:getHurtMoveParams()
--     -- local space = LocationConfig:getWidthOnEntityLayer(Constant.BattleHurtMoveLength)
--     -- local backTime = Constant.BattleHurtMoveTime*Constant.BattleHurtBackTimeRate
--     -- local frontTime = Constant.BattleHurtMoveTime - backTime

--     --平均速度计算
--     -- local backSpeed = space/backTime
--     -- local frontSpeed = space/frontTime
--     local length = 0
--     if durTime < params.backTime then
--         --如果在后退
--         length = params.backSpeed*durTime
--     else
--         --如果在前进
--         length = params.space - params.frontSpeed*(durTime - params.backTime)
--     end
--     local posX = self._currentPositionX - length*self.dir
--     self:setX(posX)
-- end

function Actor:weak()
    local aniName = "weak"
    local isAniPlaying = self:isPlayingAni(aniName)
    if not isAniPlaying then
        self:playAni({name = aniName})
    end
end

function Actor:playing()
    if (not self._armature) or (not self._armature:isPlaying()) then
        return nil
    end
    return self._armature:getLastAnimationName()
end

function Actor:playingHurt()
    local isAniPlaying = self:playing() == self.hurtAni
    return isAniPlaying
end

function Actor:playingFall()
    local isAniPlaying = self:playing() == defaultFallAnimationName
    return isAniPlaying
end

function Actor:dead()
    local deathSound = self.deathSound
    if deathSound then
        local audioID = AM.play(deathSound, false)
        if self._volume and audioID then
            AM.setVolume(audioID, self._volume)
        end
    end

    self.effectController:applyNone()

    local function deadEndCallback()
        local isSummonActor = self:isSummon()
        local isRefreshActor = self:isRefresh()
        local canRevive = self:getCanRevive()
        local needRemove = (isSummonActor or isRefreshActor) and (not canRevive) -- 应该与c++逻辑一致

        local needHide = not (self.buildingType > 0 or self.bHero or (self:isOurTeam() and canRevive))
        if self:isSelf() then
            self:dispatchEvent(Actor.Event_onShowDeadTips)
        end
        if needHide or needRemove then
            self:onDeadEnd(needRemove)
        end
    end

    local function animationEnd()
        local deadActions = {}
--        table.insert(deadActions,cc.DelayTime:create(0.0))
        table.insert(deadActions,cc.CallFunc:create(function()
            self:playDeadEffect()
        end))
--        table.insert(deadActions,cc.DelayTime:create(0.0))
        table.insert(deadActions,cc.CallFunc:create(function()
            deadEndCallback()
        end))
        local action = cc.Sequence:create(deadActions)
        action:setTag(Enums.CommonActionTag.BattleActorDeadAnimationEnd)
        self:runAction(action)
    end

    self:once("dead", animationEnd)

    self:setDeadCtrlStatusVisible(true)
end

function Actor:onDeadEnd(needRemove, _time)
    if self._prevSkillId == Constant.BattleScreenBlinkSkillId1 or self._prevSkillId == Constant.BattleScreenBlinkSkillId2 then
        self:stopScreenBlink()
        self._prevSkillId = nil
    end
    local time = _time or 0.2

    if self._playerNode then
        local act2 = cca.seq({cca.fadeOut(time),cca.callFunc(function()
            if self._playerNode then
                local isLeft = self._playerNode:isLeftSide()
                self._playerNode:setSortWeight(0)
                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, isLeft)
                if needRemove then
                    self:clearPlayerNode()
                else
                    self._playerNode:retain()
                    self._playerNode:removeFromParent(false)
                end
            end
        end)})
        act2:setTag(Enums.CommonActionTag.BattleActorReborn)
        self._playerNode:runAction(act2)
    end

    local act1 = cca.seq({cca.fadeOut(time),cca.callFunc(function()
        if needRemove then
            self:clear()
            self:removeFromParent()
        else
            CCNode_setVisible(self._armature, false)
        end
    end)})
    act1:setTag(Enums.CommonActionTag.BattleActorReborn)
    self._armature:runAction(act1)


    if needRemove then
        self:dispatchEvent(Actor.Event_onDeadEnd,self:getId())
        self:clearBuffView() --在移除自己之前清除掉buffview
    end
end

function Actor:clearBuffView()
    self:dispatchEvent(Actor.Event_onClearBuffViews,self.buffDict)
end

function Actor:once(aniName, callback, isNotCheckPlaying)
    if isNotCheckPlaying then
        self:playAni({name=aniName,playTimes = 1, completeCallback = callback})
    else
        local isAniPlaying = self:isPlayingAni(aniName)
        if not isAniPlaying then
            self:playAni({name=aniName,playTimes = 1, completeCallback = callback})
        end
    end
end

function Actor:setIdleAni(idle)
    self.idleAni = (idle or defaultIdleAnimationName)
end

function Actor:setHurtAni(name)
    self.hurtAni = name or defaultHurtAnimationName
end

function Actor:getReleasePoint()
    local slotPosX, slotPosY = self:getBonePos("hitpoint")
    return slotPosX, slotPosY
end

function Actor:turn(towards)
    if towards == Enums.Face.left then
        --面朝左
        self:turnLeft()
    elseif towards == Enums.Face.right then
        --面朝右
        self:turnRight()
    end
end

function Actor:turnLeft()
    self:face(-1)
end

function Actor:turnRight()
   self:face(1)
end

function Actor:facing()
    return self.dir
end

function Actor:face(facing)
    if self.dir ~= facing then
    self.dir = facing
    self:updateDir()
    end
end

function Actor:updateDir()
    local armature = self._armature
    local scaleX = math_abs(armature:getScaleX())
    CCNode_setScaleX(armature,scaleX*-self.dir)

    for k,v in pairs(self.followDirItems) do
        v:setPositionX(self.selectExcursion*self.dir)
    end

    local facing = self:facing()
    for _,buffView in pairs(self.buffDict) do
        buffView:face(facing)
    end

    for _,effectView in pairs(self.effectsFollowDir) do
        effectView:face(facing)
    end
end

function Actor:setX(x)
    self._currentPositionX = x
    CCNode_setPositionX(self,x)
end

function Actor:setY(y)
    self._currentPositionY = y
    CCNode_setPositionY(self,y)
end

function Actor:setTargetX(x)
    self._targetX = x
end

function Actor:updatePos(dt)
    local deltaX = self._targetX - self._currentPositionX
    local deltaXAbs = math.abs(deltaX)
    if deltaXAbs > 0 then
        local dir = deltaX / deltaXAbs
        local realDeltaX = LocationConfig:getWidthOnEntityLayer(self.moveSpeed) * dt * 1000 * dir
        self:setX(self._currentPositionX + realDeltaX)
    end
end

function Actor:setY(deltaY)
    local armature = self._armature
     if armature then
        CCNode_setPositionY(armature,self.height * self:getScale()+deltaY)
    end
end

function Actor:setMoveSpeed(speed, baseSpeed)
    self.moveSpeed = speed
    local aniName = "move"
    local isAniPlaying = self:isPlayingAni(aniName)
    if isAniPlaying then
        local percent = speed/baseSpeed
        self:setTimeScale(percent)
    end
end

function Actor:getMoveSpeed()
    return self.moveSpeed
end

function Actor:move()
    local aniName = "move"
    local isAniPlaying = self:isPlayingAni(aniName)
    if not isAniPlaying then
        self:playAni({name=aniName})
    end
end

function Actor:idle()
    local aniName = self.idleAni
    local isAniPlaying = self:isPlayingAni(aniName)
    if not isAniPlaying then
         -- print("---not isAniPlaying aniName:"..aniName)
        self:playAni({name=aniName})
    end
end

function Actor:chant(aniName)
    -- print("---------Actor:chant aniName:"..aniName.."----id:"..self:getId())
    if aniName and string_len(aniName) > 0 then
        -- print("---chant aniName:"..aniName)
        local isAniPlaying = self:isPlayingAni(aniName)
        if not isAniPlaying then
             -- print("---not isAniPlaying aniName:"..aniName)
            self:playAni({name=aniName})
        end
    end
end

function Actor:track(aniName)
    -- print("---------Actor:track aniName:"..aniName.."----id:"..self:getId())
    if aniName and string_len(aniName) > 0 then
        -- print("---track aniName:"..aniName)
        local isAniPlaying = self:isPlayingAni(aniName)
        if not isAniPlaying then
             -- print("---not isAniPlaying aniName:"..aniName)
            self:playAni({name=aniName})
        end
    end
end

function Actor:skill(aniName, isCheckPlaying)
    -- print("---------Actor:skill aniName:"..aniName.."----id:"..self:getId())
    -- local aniName = self.mSkills[skillName]:getAnimation()
    if aniName and string_len(aniName) > 0 then
        if isCheckPlaying then
            local isAniPlaying = self:isPlayingAni(aniName)
            if not isAniPlaying then
                self:playAni({name=aniName})
            end
        else
            self:playAni({name=aniName})
        end
    end
end

-- function Actor:channel(aniName)
--     print("---------Actor:channel:"..aniName.."----id:"..self:getId())
--     -- local aniName = self.mSkills[skillName].channel.animation
--     if aniName and string_len(aniName) > 0 then
--         local isAniPlaying = self:isPlayingAni(aniName)
--         if not isAniPlaying then
--             self:playAni({name=aniName})
--         end
--     end
-- end

------------------------------------new end--------------------------------------

function Actor:pause()
    getmetatable(self).pause(self)
    self._armature:pause()
    self.isActionPause = true
    local children = self:getChildren()
    for i=1, self:getChildrenCount() do
        local child = children[i]
        child:pause()
    end

    for i,v in pairs(self.effectEmitters) do
        v:pause()
    end

    for _,v in pairs(self.chantEffectEmitters) do
        if v then
            v:pause()
        end
    end
end

function Actor:resume()
    getmetatable(self).resume(self)
    self._armature:resume()
    self.isActionPause = false
    local children = self:getChildren()
    for i=1, self:getChildrenCount() do
        local child = children[i]
        child:resume()
    end

    for i,v in pairs(self.effectEmitters) do
        v:resume()
    end

    for _,v in pairs(self.chantEffectEmitters) do
        if v then
            v:resume()
        end
    end
end

function Actor:setNodeColor(color)
    self:setColor(color)
    --测试用 todo 暂时不随主角做明暗变化
    local skillNameLayout = self._skillNameLayout
    if skillNameLayout then
        skillNameLayout:setColor(color)
        local children = skillNameLayout:getChildren()
        for i=1, self:getChildrenCount() do
            local child = children[i]
            if child then
                child:setColor(color)
            end
        end
    end
end

function Actor:isPause()
    return self.isActionPause
end

function Actor:setArmature(armature)
    if self._armature then
        self._armature:removeAllEventListeners()
        self:removeChild(self._armature)
        self._armature=nil
    end

    if armature then
        self._armature = armature
        self.originScale = armature:getScale()
        if self._volume then
            self._armature:setVolume(self._volume)
        end
        armature:onFrameEvent(handler(self,Actor.handleFrameEvent))
        self:addChild(self._armature,ZOrderList.DB)
        --self:setScale(oldScale)
        armature:setMotionStreakFadetime(1.5)
        armature:setMotionStreakOffset(-20,50)
    end
    self:refreshArmatureAutoSound()
end

function Actor:refreshArmatureAutoSound()
    if self._armature then
        self._armature:setAutoPlaySound(self.actorType == Enum_BattleActorType_self)
    end
end

function Actor:getArmature()
    return self._armature
end

function Actor:getBoundingBox()
    return self._armature:getBoundingBox()
end

function Actor:getAniDuration(aniName)
    return self._armature:getAniDuration(aniName)
end

function Actor:isPlaying(aniName)
    local lastName = self._armature:getLastAnimationName()
    return self._armature and string.find(lastName, aniName) == 1

    -- return self._armature and self._armature:isPlaying(aniName)
end

function Actor:getAnimationList()
    return self._armature:getAnimationList()
end

function Actor:playAni(params)
    if params then
        if params.ignore_prefix==nil then
            params.name = (self.aniPrefix..params.name)
            if params.next then
                params.next = (self.aniPrefix..params.next)
            end
        end
        -- if not params.fadeInTime then
            -- 临时修改，所有角色fadeIn效果移除
            params.fadeInTime = 0
        -- end

        --如果播放其他动画，恢复正常动画速度
        if params.name ~= "move" then
            self:setTimeScale(self.animTimeScale)
        end

        return self._armature:playAni(params)
    else
        self._armature:play()
        return true
    end
end

function Actor:handleFrameEvent(armature,frameLabel)
    --print("handleFrameEvent : ",event.animation,event.frameLabel)
    for i,v in pairs(self.effectEmitters) do
        if v:canFire(frameLabel) then
            v:fire()
        end
    end

    for i,v in pairs(self.chantEffectEmitters) do
        if v and v:canRemove(frameLabel) then
            self.chantEffectEmitters[v.id]=nil
            v:remove()
        end
    end

    for i,v in pairs(self.chantEffectEmitters) do
        if v and v:canFire(frameLabel) then
            v:fire()
        end
    end

    for _,sfxPlayer in pairs(self.sfxList) do
        if sfxPlayer:canPlay(frameLabel) then
            sfxPlayer:play()
        end
    end
end

function Actor:setIdleAni(idle)
    self.idleAni = (idle or defaultIdleAnimationName)
    self:playIdle()
end

function Actor:setHurtAni(name)
    self.hurtAni = name or defaultHurtAnimationName
end

function Actor:playIdle(startCB)
    self:playAni({name = self.idleAni,startCallback=startCB})
end

function Actor:isPlayingIdle()
    return self:isPlaying(self.aniPrefix..self.idleAni)
end

function Actor:isPlayingAni(aniName)
    return self:isPlaying(self.aniPrefix..aniName)
end

function Actor:playSoul(startCB)
    self:playAni({name="soul",ignore_prefix=true,fadeInTime=0,startCallback=startCB})
end

function Actor:playVictory(startPixel,screenScale)
    local armature = self:getArmature()
    local victoryAni = "win"

    if not armature:hasAnimation(victoryAni) then
        self:playIdle()
    else
        --如果是敌方，会退场
        local function completeCb()
            if self.actorType == Enum_BattleActorType_enemy or self.actorType == Enums.BattleActorType.boss then
                local random = math.random(1,100)%2
                local dir = 1
                if random == 0 then
                    dir = -1
                end
                --改变方向
                local scaleX = math_abs(armature:getScaleX())
                armature:setScaleX(scaleX*-dir)

                local posY = self:getPositionY()
                local posX = self:getPositionX()
                if dir == 1 then
                    posX = startPixel + display.width*screenScale + 100
                else
                    posX = startPixel - 100
                end
                self:runTo(cc.p(posX,posY),300,nil,nil)
                local randomTime = 0.9 + (math.random(1,100)%3)*0.1
                local actions = {}
                table.insert(actions, cc.DelayTime:create(randomTime))
                table.insert(actions, cc.FadeOut:create(0.5))
                table.insert(actions, cc.CallFunc:create(function()
                    self:setVisible(false)
                end))
                armature:runAction(cc.Sequence:create(actions))

                self:hideAllEffect()
            end
        end
        self:playAni({name=victoryAni,ignore_prefix=true,fadeInTime=0,completeCallback = completeCb})
    end
end

function Actor:isHero()
    return self.bHero
end

function Actor:playFailure()
    local armature = self:getArmature()
    CCNode_setVisible(armature, true)
    local failAni = "dead"

    if not armature:hasAnimation(failAni) then
        self:playIdle()
    else
        self:playAni({name=failAni, ignore_prefix=true, fadeInTime=0})
    end
end

function Actor:playMVPVictory(startPixel,screenScale)
    local armature = self:getArmature()
    CCNode_setVisible(armature, true)
    local victoryAni = "win"

    if not armature:hasAnimation(victoryAni) then
        self:playIdle()
    else
        self:playAni({name=victoryAni, ignore_prefix=true, fadeInTime=0, next = self.idleAni})
    end
end

function Actor:playEscape(startPixel,screenScale)
    local armature = self:getArmature()
    local function playAction()
        local dir = 1
        if self.initDir == 1 then
            dir = -1
        end
        armature:stopActionByTag(Enum_CommonActionTag_BattleArmatureBuffScale)
        self.dir = dir
        -- print("==========Actor:playEscape============dir:",dir)
        --改变方向
        local scaleX = math_abs(armature:getScaleX())
        armature:setScaleX(scaleX*-dir)

        local posY = self:getPositionY()
        local posX = self:getPositionX()
        if dir == 1 then
            posX = startPixel + display.width*screenScale + 100
        else
            posX = startPixel - 100
        end
        self:runTo(cc.p(posX,posY),300,nil,nil)
    end

    local randomTime = 0.9 + (math.random(1,100)%3)*0.1
    local actions = {}
    table.insert(actions, cc.CallFunc:create(playAction))
    table.insert(actions, cc.DelayTime:create(randomTime))
    table.insert(actions, cc.FadeOut:create(0.5))
    table.insert(actions, cc.CallFunc:create(function()
        self:setVisible(false)
    end))
    armature:runAction(cc.Sequence:create(actions))

    self:hideAllEffect()
end

function Actor:setOutline(bShow)
    self.bEnableOutline = bShow
end

function Actor:hideAllEffect()
    if self._warningNode then
        self._warningNode:setVisible(false)
    end

    if self.mIMBubble then
        self.mIMBubble:setVisible(false)
    end

    if self.bubbleRoot then
        self.bubbleRoot:setVisible(false)
    end

    self:displayOutlineEffect(false)
end

function Actor:runTo(pos,speed,callback,delay)
    -- self:playAni({name="move"})
    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local actions = {}

    self:stopRunToAction()

    local runAniName = "move"
    local isMoveAniPlaying = self:isPlayingAni(runAniName)
    if delay then
        table.insert(actions,cc.DelayTime:create(delay))
        if not isMoveAniPlaying then
            table.insert(actions,cc.CallFunc:create(function() self:playAni({name=runAniName}) end))
        end
    else
        -- if not isMoveAniPlaying then
            self:playAni({name=runAniName})
        -- end
    end
    table.insert(actions,cc.MoveTo:create(duration,pos))
    table.insert(actions,cc.CallFunc:create(function() self:playIdle() end))
    table.insert(actions,cc.DelayTime:create(0.1))
    if callback then
        table.insert(actions,cc.CallFunc:create(callback))
    end
    local runToAction = cc.Sequence:create(actions)
    runToAction:setTag(Enums.CommonActionTag.ActorRunTo)
    self:runAction(runToAction)
end

function Actor:setTimeScale(scale)
    local armature = self:getArmature()
    if armature then
        armature:setTimeScale(scale)
    end
end

function Actor:backTo(pos,speed,callback)
    -- self:playAni({name="move"})
    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local actions = {}
    actions[1] = cc.MoveTo:create(duration,pos)
    actions[2] = cc.DelayTime:create(0.1)
    if callback then
        actions[3] = cc.CallFunc:create(callback)
    end
    local runToAction = cc.Sequence:create(actions)
    runToAction:setTag(Enums.CommonActionTag.ActorRunTo)
    self:runAction(runToAction)
end

function Actor:jumpTo(pos,speed,callback)
    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local height = math_abs(self:getPositionX()-pos.x) * 0.3
    local actions = {}
    table.insert(actions,cc.JumpTo:create(duration,pos,height,1))
    if callback then
        table.insert(actions,cc.CallFunc:create(callback))
    end
    self:runAction(cc.Sequence:create(actions))
end

function Actor:jumpToWithAni(pos,speed,callback,delay)
    -- self:playAni({name="jumpdown"})
    local function endAction()
        local endActions = {}
        table.insert(endActions,cc.CallFunc:create(function() self:playIdle() end))
        if callback then
            table.insert(endActions,cc.CallFunc:create(callback))
        end
        self:runAction(cc.Sequence:create(endActions))
    end

    local function jumpDownAction()
        local armatureActions= {}
        local armature = self:getArmature()
        local duration = armature:getAniDuration("jumpbuffer")
        local aniAct = db.DBAnimate:create(duration,"jumpbuffer")
        table.insert(armatureActions,aniAct)
        table.insert(armatureActions,cc.CallFunc:create(endAction))
        armature:runAction(cc.Sequence:create(armatureActions))
    end

    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local height = math_abs(self:getPositionX()-pos.x) * 0.1
    local actions = {}
    if delay then
        table.insert(actions,cc.DelayTime:create(delay))
        table.insert(actions,cc.CallFunc:create(function() self:playAni({name="jumpdown"}) end))
    else
        self:playAni({name="jumpdown"})
    end
    table.insert(actions,cc.JumpTo:create(duration,pos,height,1))
    -- table.insert(actions,cc.CallFunc:create(function() self:playIdle() end))
    -- if callback then
    --     table.insert(actions,cc.CallFunc:create(callback))
    -- end

    table.insert(actions,cc.CallFunc:create(jumpDownAction))
    self:runAction(cc.Sequence:create(actions))



end

function Actor:flashTo(pos,callback)
    local actions = {}
    table.insert(actions,cc.Place:create(pos))
    if callback then
        table.insert(actions,cc.CallFunc:create(callback))
    end
    self:runAction(cc.Sequence:create(actions))
end

function Actor:rushTo(pos,speed,callback)
    self:playAni({name="jumpup"})
    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local actions = {}
    table.insert(actions,cc.MoveTo:create(duration,pos))
    if callback then
        table.insert(actions,cc.CallFunc:create(callback))
    end
    self:runAction(cc.Sequence:create(actions))
end

function Actor:rushBack(pos,speed,callback)
    self:playAni({name="jumpdown"})
    local dis = cc.pGetDistance(cc.p(self:getPosition()),pos)
    local duration = dis/speed
    local actions = {}
    table.insert(actions,cc.MoveTo:create(duration,pos))
    if callback then
        table.insert(actions,cc.CallFunc:create(callback))
    end
    self:runAction(cc.Sequence:create(actions))
end

--停止runto action
function Actor:stopRunToAction()
    self:stopActionByTag(Enums.CommonActionTag.ActorRunTo)
end

function Actor:bornIdle(duration,callback)
    if duration and tonumber(duration) > 0 then
        local aniName = (self.idleAni or nil)
        if aniName and duration>0 and self:getArmature():hasAnimation(aniName) then
            local actions = {}
            local aniAct = db.DBAnimate:create(duration,aniName)
            table.insert(actions,aniAct)
            self:getArmature():clearNextAni()

            table.insert(actions,cc.CallFunc:create(function()
                if callback then
                    callback()
                end
            end))
            self:getArmature():runAction(cc.Sequence:create(actions))
        else
            if callback then
                callback()
            end
        end
    else
        if callback then
            callback()
        end
    end
end

function Actor:gotoWith(t,pos,speed,callback)
    if t == 1 then
        self:rushTo(pos,speed,callback)
    elseif t==2 then
        self:flashTo(pos,callback)
    elseif t==3 then
        self:jumpTo(pos,speed,callback)
    else
        if callback then
            callback()
        end
    end
end

function Actor:gobackWith(type,pos,speed,callback)
    if type == 1 then
        self:rushBack(pos,speed,callback)
    elseif type==2 then
        self:flashTo(pos,callback)
    elseif type==3 then
        self:jumpTo(pos,speed,callback)
    else
        if callback then
            callback()
        end
    end
end

function Actor:getBonePos(boneName)
    return self._armature:getBonePos(boneName)
end

function Actor:getBoneLocalPos(boneName)
    local posX,posY = self:getBonePos(boneName)
    return CCNode_toLocalPosition(self,posX,posY)
end

function Actor:getFireLocalPos()
    return self:getBoneLocalPos("hitpoint")
end

function Actor:getFirePos()
    return self:getBonePos("hitpoint")
end

function Actor:getBuffHitPos()
    local posX,posY = 0,0
    local ret = false
    for _,buffView in pairs(self.buffDict) do
        local ret,x,y = buffView:genRandomHitPos()
        if ret then
            ret = true
            posX = x
            posY = y
            break
        end
    end
    return ret,posX,posY
end

function Actor:getHitPos()
    local ret ,buffHitPosX,buffHitPosY = self:getBuffHitPos()
    if ret then
        return buffHitPosX,buffHitPosY
    else
        return self:getBonePos("body")
    end
end

function Actor:getHitLocalPos()
    local posX,posY = self:getHitPos()
    return CCNode_toLocalPosition(self,posX,posY)
end

function Actor:getBuffHitLocalPos()
    local ret ,posX,posY = self:getBuffHitPos()
    if ret then
        return ret,CCNode_toLocalPosition(self,posX,posY)
    end
    return ret,posX,posY
end

function Actor:getHeadPos()
    local x,y = self._pointPosX,self._pointPosY
    local armature = self._armature
    if self._pointPosDirty and armature then
        x,y = Armature_getBoneWorldPosition(armature,"point")
        self._pointPosX = x
        self._pointPosY = y
        self._pointPosDirty = false
    end
    return x,y
end

function Actor:getHeadLocalPos()
    return CCNode_toLocalPosition(self,self:getHeadPos())
end

function Actor:displayOutlineEffect(b,colorType)
    -- cancel outline enemy when dead

    if b and self:isDead() and not self:isOurTeam() or not self.bEnableOutline  then
        local armature = self:getArmature()
        armature:enableOutline(false)
        return
    end

    local armature = self:getArmature()
    armature:enableOutline(b)
    if colorType == 1 then --self
        armature:setOutlineColor(255,215,31)
    elseif colorType == 2 then --target
        armature:setOutlineColor(255,18,18)
    elseif colorType == 3 then --team target
        armature:setOutlineColor(31,210,255)
    end
    armature:setOutlineSize(6)
end

function Actor:displayRedArrowMark(b)
    if self.redMarkArrow==nil and b then
        self.redMarkArrow = display.newArmature({path="armatures/effect/roleselect",armatureName="roleselect",animationName="",skeletonName="roleselect"})
        self:addChild(self.redMarkArrow,ZOrderList.SelectMarkArrow+1)
        self.redMarkArrow:getAnimation():gotoAndPlay("red_arrow")
        local headPosX,headPosY = self:getHeadLocalPos()
        self.redMarkArrow:setPosition(0,headPosY)
    end

    if self.redMarkArrow then
        local oldVisible = self.redMarkArrow:isVisible()
        if oldVisible ~= b then
            self.redMarkArrow:setVisible(b)
            if b then
                self.redMarkArrow:getAnimation():gotoAndPlay("red_arrow")
            else
                self.redMarkArrow:getAnimation():stop()
            end
        end
    end
end

function Actor:displayGreenArrowMark(b)
    if self.greenMarkArrow==nil and b then
        self.greenMarkArrow = display.newArmature({path="armatures/effect/roleselect",armatureName="roleselect",animationName="",skeletonName="roleselect"})
        self:addChild(self.greenMarkArrow,ZOrderList.SelectMarkArrow+1)
        self.greenMarkArrow:getAnimation():gotoAndPlay("green_arrow")
        local headPosX,headPosY = self:getHeadLocalPos()
        self.greenMarkArrow:setPosition(0,headPosY)
    end

    if self.greenMarkArrow then
        local oldVisible = self.greenMarkArrow:isVisible()
        if oldVisible ~= b then
            self.greenMarkArrow:setVisible(b)
            if b then
                self.greenMarkArrow:getAnimation():gotoAndPlay("green_arrow")
            else
                self.greenMarkArrow:getAnimation():stop()
            end
        end
    end
end

-- function Actor:displayGreenMark(b)
--      if self.greenMarkNode==nil then
--         self.greenMarkNode = display.newArmature({path="armatures/effect/roleselect",armatureName="roleselect",animationName="",skeletonName="roleselect"})
--         self:addChild(self.greenMarkNode,ZOrderList.SelectMark)
--         self.greenMarkNode:getAnimation():play("green")
--     end

--     self.greenMarkNode:setVisible(b)
--     --self.greenMarkArrow:setVisible(b)
-- end

-- function Actor:displayInputMark(b,opacity)
--     local node = self.inputMarkNode
--     if node==nil then
--         node = display.newArmature({path="armatures/effect/roleselect",armatureName="selectmark",animationName="",skeletonName="roleselect"})
--         self:addChild(node,ZOrderList.SelectMarkArrow)
--         local headPosX,headPosY = self:getHeadLocalPos()
--         node:setPosition(headPosX,headPosY)
--         node:getAnimation():play("blue")
--         self.inputMarkNode = node
--     end
--     node:setVisible(b)
--     node:setOpacity(opacity)
-- end

function Actor:playDeadEffect()
    local node = self.deadEffectNode
    if node==nil then
        node = display.newArmature({path=Res.DeadEffect.dir,armatureName=Res.DeadEffect.name,animationName="",skeletonName=Res.DeadEffect.name})
        self:addChild(node,ZOrderList.DeadEffect)
        node:getAnimation():play()
        node:setScale(2.0)
        self.deadEffectNode = node
    end
end

function Actor:playReviveEffect()
    if self.reviveEffectNode == nil then
	    self.reviveEffectNode = Armature.create({path=Res.ActorReviveEffect.dir,armatureName=Res.ActorReviveEffect.name,animationName=""})

        self:addChild(self.reviveEffectNode,ZOrderList.ReviveEffect)
        self.reviveEffectNode:setPosition(self:getBoneLocalPos("body"))
        self.reviveEffectNode:setVisible(false)
    end

    if self.reviveEffectNode and not self.reviveEffectNode:isVisible() then
        self.reviveEffectNode:setVisible(true)
        self.reviveEffectNode:playAni({name="doing",playTimes = 1,completeCallback=function()
            self.reviveEffectNode:setVisible(false)
        end})
    end
end

function Actor:showSelectMark(bSelected)
   if self.selectEffect == nil and bSelected then
       self.selectEffect = display.newArmature({path=Res.ActorSelectEffect.dir,armatureName=Res.ActorSelectEffect.name,animationName="",skeletonName=Res.ActorSelectEffect.name})
       self:addChild(self.selectEffect,ZOrderList.SelectEffect)
       self.selectEffect:getAnimation():play()

       self.selectEffect:setScale(2*self.selectSize/100)
       if self.selectExcursion ~= 0 then
            self.selectEffect:setPositionX(self.selectExcursion*self.dir)
            table.insert(self.followDirItems, self.selectEffect)
        end
    end

    if self.selectEffect then
        -- self.selectEffect:resume()
        self.selectEffect:setVisible(bSelected)
    end
end

function Actor:showTouchEndEffect(b)
    if self:isSelfTeam() then
        self:showTeamTouchEndEffect(b)
        self:showTeamTouchEndArrowEffect(b)
    else
        self:showEnemyTouchEndEffect(b)
        self:showEnemyTouchEndArrowEffect(b)
    end
--    if self.touchEndEffect == nil and b then
--         local Armature = app:getClass("Armature")
-- 	    self.touchEndEffect = Armature.create({path=Res.ActorTouchEndEffect.dir,armatureName=Res.ActorTouchEndEffect.name,animationName=""})
--         -- self.touchEndEffect = display.newArmature({path=Res.ActorTouchEndEffect.dir,armatureName=Res.ActorTouchEndEffect.name,animationName="",skeletonName=Res.ActorTouchEndEffect.name})
--         -- self.touchEndEffect:getAnimation():play()

--         self:addChild(self.touchEndEffect,ZOrderList.TouchEndEffect)
--         self.touchEndEffect:setPosition(self:getBoneLocalPos("body"))
--         self.touchEndEffect:setScale(2)

--     --    self.touchEndEffect:setScale(2*self.selectSize/100)
--     --    if self.selectExcursion ~= 0 then
--     --         self.touchEndEffect:setPositionX(self.selectExcursion*self.dir)
--     --         table.insert(self.followDirItems, self.touchEndEffect)
--     --     end
--     end

--     if self.touchEndEffect then
--         self.touchEndEffect:setVisible(b)
--         if b then
--             self.touchEndEffect:playAni({name="pointselect",playTimes = 1,completeCallback=function()
--                 self.touchEndEffect:setVisible(false)
--             end})
--         end
--     end
end

function Actor:refreshSelectEffect()
    if self.isCurrentPlayerTarget then
        if self:isSelfTeam() then
            if not self.teamTouchEndEffect then
                self:showTeamTouchEndEffect(true)
            else
                self.teamTouchEndEffect:setVisible(true)
            end

            if not self.teamTouchEndArrowEffect then
                self:showTeamTouchEndArrowEffect(true)
            else
                self.teamTouchEndArrowEffect:setVisible(true)
            end
        else
            if not self.enemyTouchEndEffect then
                self:showEnemyTouchEndEffect(true)
            else
                self.enemyTouchEndEffect:setVisible(true)
            end

            if not self.enemyTouchEndArrowEffect then
                self:showEnemyTouchEndArrowEffect(true)
            else
                self.enemyTouchEndArrowEffect:setVisible(true)
            end
        end
    else
        -- 如果不是选中目标
        if self:isSelfTeam() then
            if self.teamTouchEndEffect and self.teamTouchEndEffect:isVisible() then
                self.teamTouchEndEffect:setVisible(false)
            end

            if self.teamTouchEndArrowEffect and self.teamTouchEndArrowEffect:isVisible() then
                self.teamTouchEndArrowEffect:setVisible(false)
            end
        else
            if self.enemyTouchEndEffect and self.enemyTouchEndEffect:isVisible() then
                self.enemyTouchEndEffect:setVisible(false)
            end

            if self.enemyTouchEndArrowEffect and self.enemyTouchEndArrowEffect:isVisible() then
                self.enemyTouchEndArrowEffect:setVisible(false)
            end
        end
    end
end

function Actor:showTeamTouchEndEffect(b)
   if self.teamTouchEndEffect == nil and b then
	    self.teamTouchEndEffect = Armature.create({path=Res.ActorTeamTouchEndEffect.dir,armatureName=Res.ActorTeamTouchEndEffect.name,animationName=""})
        -- self.teamTouchEndEffect = display.newArmature({path=Res.ActorTeamTouchEndEffect.dir,armatureName=Res.ActorTeamTouchEndEffect.name,animationName="",skeletonName=Res.ActorTeamTouchEndEffect.name})
        -- self.teamTouchEndEffect:getAnimation():play()

        self.teamTouchEndEffect:setScale(self.selectSize/100)
        self:addChild(self.teamTouchEndEffect,ZOrderList.TouchEndEffect)
        -- self.teamTouchEndEffect:setPosition(self:getBoneLocalPos("body"))
        -- self.teamTouchEndEffect:setScale(2)

    --    self.teamTouchEndEffect:setScale(2*self.selectSize/100)
       if self.selectExcursion ~= 0 then
            self.teamTouchEndEffect:setPositionX(self.selectExcursion*self.dir)
            table.insert(self.followDirItems, self.teamTouchEndEffect)
        end
    end

    if self.teamTouchEndEffect then
        self.teamTouchEndEffect:setVisible(b)
        if b then
            self.teamTouchEndEffect:playAni({name="xzjfcreat",playTimes = 1,completeCallback=function()
                if not self.isCurrentPlayerTarget then
                    self.teamTouchEndEffect:setVisible(false)
                end
            end})
        end
    end
end

function Actor:showTeamTouchEndArrowEffect(b)
   if self.teamTouchEndArrowEffect == nil and b then
	    self.teamTouchEndArrowEffect = Armature.create({path=Res.ActorTeamTouchEndArrowEffect.dir,armatureName=Res.ActorTeamTouchEndArrowEffect.name,animationName=""})
        -- self.teamTouchEndArrowEffect = display.newArmature({path=Res.ActorTeamTouchEndArrowEffect.dir,armatureName=Res.ActorTeamTouchEndArrowEffect.name,animationName="",skeletonName=Res.ActorTeamTouchEndArrowEffect.name})
        -- self.teamTouchEndArrowEffect:getAnimation():play()

        -- self.teamTouchEndArrowEffect:setScale(self.selectSize/100)
        self:addChild(self.teamTouchEndArrowEffect,ZOrderList.TouchEndEffect)
        local headPosX,headPosY = self:getHeadLocalPos()
        self.teamTouchEndArrowEffect:setPosition(headPosX, headPosY + 80)

    --    if self.selectExcursion ~= 0 then
    --         self.teamTouchEndArrowEffect:setPositionX(self.selectExcursion*self.dir)
    --         table.insert(self.followDirItems, self.teamTouchEndArrowEffect)
    --     end
    end

    if self.teamTouchEndArrowEffect then
        self.teamTouchEndArrowEffect:setVisible(b)
        if b then
            self.teamTouchEndArrowEffect:playAni({name="xzjfcreat",playTimes = 1,completeCallback=function()
                if not self.isCurrentPlayerTarget then
                    self.teamTouchEndArrowEffect:setVisible(false)
                end
            end})
        end
    end
end

function Actor:showEnemyTouchEndEffect(b)
   if self.enemyTouchEndEffect == nil and b then
	    self.enemyTouchEndEffect = Armature.create({path=Res.ActorEnemyTouchEndEffect.dir,armatureName=Res.ActorEnemyTouchEndEffect.name,animationName=""})
        -- self.enemyTouchEndEffect = display.newArmature({path=Res.ActorEnemyTouchEndEffect.dir,armatureName=Res.ActorEnemyTouchEndEffect.name,animationName="",skeletonName=Res.ActorEnemyTouchEndEffect.name})
        -- self.enemyTouchEndEffect:getAnimation():play()

        self.enemyTouchEndEffect:setScale(self.selectSize/100)
        self:addChild(self.enemyTouchEndEffect,ZOrderList.TouchEndEffect)
        -- self.enemyTouchEndEffect:setPosition(self:getBoneLocalPos("body"))
        -- self.enemyTouchEndEffect:setScale(2)

    --    self.enemyTouchEndEffect:setScale(2*self.selectSize/100)
       if self.selectExcursion ~= 0 then
            self.enemyTouchEndEffect:setPositionX(self.selectExcursion*self.dir)
            table.insert(self.followDirItems, self.enemyTouchEndEffect)
        end
    end

    if self.enemyTouchEndEffect then
        self.enemyTouchEndEffect:setVisible(b)
        if b then
            self.enemyTouchEndEffect:playAni({name="xzdfcreat",playTimes = 1,completeCallback=function()
                if not self.isCurrentPlayerTarget then
                    self.enemyTouchEndEffect:setVisible(false)
                end
            end})
        end
    end
end

function Actor:showEnemyTouchEndArrowEffect(b)
   if self.enemyTouchEndArrowEffect == nil and b then
	    self.enemyTouchEndArrowEffect = Armature.create({path=Res.ActorEnemyTouchEndArrowEffect.dir,armatureName=Res.ActorEnemyTouchEndArrowEffect.name,animationName=""})
        -- self.enemyTouchEndArrowEffect = display.newArmature({path=Res.ActorEnemyTouchEndArrowEffect.dir,armatureName=Res.ActorEnemyTouchEndArrowEffect.name,animationName="",skeletonName=Res.ActorEnemyTouchEndArrowEffect.name})
        -- self.enemyTouchEndArrowEffect:getAnimation():play()

        -- self.enemyTouchEndArrowEffect:setScale(self.selectSize/100)
        self:addChild(self.enemyTouchEndArrowEffect,ZOrderList.TouchEndEffect)
        local headPosX,headPosY = self:getHeadLocalPos()
        self.enemyTouchEndArrowEffect:setPosition(headPosX, headPosY + 80)

    --    if self.selectExcursion ~= 0 then
    --         self.enemyTouchEndArrowEffect:setPositionX(self.selectExcursion*self.dir)
    --         table.insert(self.followDirItems, self.enemyTouchEndArrowEffect)
    --     end
    end

    if self.enemyTouchEndArrowEffect then
        self.enemyTouchEndArrowEffect:setVisible(b)
        if b then
            self.enemyTouchEndArrowEffect:playAni({name="xzdfcreat",playTimes = 1,completeCallback=function()
                if not self.isCurrentPlayerTarget then
                    self.enemyTouchEndArrowEffect:setVisible(false)
                end
            end})
        end
    end
end



function Actor:showTargetedEffect(b, rangeDisplay, dir)
    if self.targetedEffect == nil and b then
       self.targetedEffect = display.newArmature({path=Res.ActorTargetedEffect.dir,armatureName=Res.ActorTargetedEffect.name,animationName="",skeletonName=Res.ActorTargetedEffect.name, async = false,})
       self:addChild(self.targetedEffect,ZOrderList.TargetedEffect)
    --    self.targetedEffect:setScale(1.4)
       self.targetedEffect:getAnimation():play()
    end

    if self.targetedEffect then
        self.targetedEffect:setVisible(b)
        if rangeDisplay ~= nil then
            self.targetedEffect:setScaleX(1.0)
            local box = self.targetedEffect:getBoundingBox()
            local scale = rangeDisplay/(box.width*LocationConfig:getScreenScale())
            -- local actorScale = self:getScale()
            --print("Actor:showTargetedEffect scale", scale, "box.width",box.width,"actorScale",actorScale)
            -- self.targetedEffect:setScaleX(scale/actorScale)
            self.targetedEffect:setScaleX(scale)
        else
            self.targetedEffect:setScaleX(1.0)
        end

        if dir == nil then
            self.targetedEffect:setPositionX(0)
        else
            self.targetedEffect:setPositionX((rangeDisplay/2)*dir)
        end
    end
end

function Actor:showSingleTargetedEffect(b)
   if self.singleTargetedEffect == nil and b then
       self.singleTargetedEffect = display.newArmature({path=Res.ActorSingleTargetedEffect.dir,armatureName=Res.ActorSingleTargetedEffect.name,animationName="",skeletonName=Res.ActorSingleTargetedEffect.name})
       self:addChild(self.singleTargetedEffect,ZOrderList.TargetedEffect)
       self.singleTargetedEffect:getAnimation():play()

       self.singleTargetedEffect:setScale(1.7)
    end

    if self.singleTargetedEffect then
        self.singleTargetedEffect:setVisible(b)
    end
end


function Actor:playReadyReleaseSkill(b)
    local node = self.readyReleaseSkillEffect
    if node==nil then
        node = display.newArmature({path=Res.ReadyReleaseEffect.dir,armatureName=Res.ReadyReleaseEffect.name,animationName="",skeletonName=Res.ReadyReleaseEffect.name})
        self:addChild(node,ZOrderList.ReleaseSkillEffect)
        -- node:getAnimation():play()
        node:getAnimation():gotoAndPlay("effloop")
        self.readyReleaseSkillEffect = node
    end
    node:setVisible(b)
end

function Actor:showFocusTargetEffect(b)
    local node = self.focusTargetEffect
    if node==nil then
        node = display.newArmature({path=Res.ActorFocusTargetEffect.dir,armatureName=Res.ActorFocusTargetEffect.name,animationName="",skeletonName=Res.ActorFocusTargetEffect.name})
        self:addChild(node,ZOrderList.FocusTarget)
        node:getAnimation():play()
        self.focusTargetEffect = node
    end
    node:setVisible(b)
end

function Actor:prepareWarningNode()
    if self._warningNode == nil and self.warningLayer then
        self._warningNode = display.newArmature({path=Res.ActorWarningEffect.dir,armatureName=Res.ActorWarningEffect.name,animationName="",skeletonName=Res.ActorWarningEffect.name})
        self.warningLayer:addChild(self._warningNode)
        self._warningNode:getAnimation():play()

        self._armature:addAttachment(self._warningNode,"point",0,50)
    end
end

function Actor:getIsWarned()
    return self.isWarned
end

function Actor:setWarning(isVisible, isWarnedForController, time, rangeKind, isMainTarget, rangeDisplay)
    if self.isWarned == isVisible then
        return
    end

    self.isWarned = isVisible

    -- local isNeedShow = false
    local isNeedShowEffect = true
    local nodeScale = 1.0
    local rangeDisplay = rangeDisplay
    local isNeedShowSingleEffect = false
    if isVisible then
        if (not rangeKind) then
            -- isNeedShow = true
            -- print("===============rangeKind nil")
        else
            if rangeKind == Enums.DamageRangeKind.DR_Kind_Single then
                -- isNeedShow = true
                if isMainTarget then
                    isNeedShowSingleEffect = true
                end
                nodeScale = 1.0
            elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Region then
                if isMainTarget then
                    -- isNeedShow = true
                    nodeScale = 1.0
                end
            elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
                -- isNeedShow = true
                nodeScale = 1.0
                isNeedShowEffect = false
            elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Screen then
                -- isNeedShow = true
            end
        end
    end

    self:prepareWarningNode()
    -- if isNeedShow or (not isVisible) then
        if self._warningNode then
            self._warningNode:setVisible(isVisible)
            self._warningNode:setScale(nodeScale)
            -- if isVisible then
            --     local timeNode = self._warningNode:findChild("eye/time")
            --     assert(timeNode)
            --     if time then
            --         timeNode:setString(time)
            --     end
            -- end
        end

        --todo
        -- if isNeedShowEffect then
        --     self:showTargetedEffect(isVisible, rangeDisplay)
        -- else
        --     self:showTargetedEffect(false, rangeDisplay)
        -- end
    -- end

    if isNeedShowSingleEffect or (not isVisible) then
        self:showSingleTargetedEffect(isVisible)
    end

    if self._playerNode then
        self._playerNode:setWarning(isVisible, time)
    end

    if isVisible then
        if self.actorType == Enum_BattleActorType_self then
            --如果是主角
            if not isWarnedForController then
                --如果没有警告过
                AM.play(Res.BattleWarningSound, false)
            end
        end
    end
end

function Actor:setStar(num,max)
    if max > 0 then
        self._statusBar:setStar(num,max,self:isDead())
    end
end

function Actor:setWarningRange(isVisible, rangeKind, rangeDisplay)
    -- local isNeedShow = false
    local isNeedShowRangeEffect = false
    local rangeDisplay = rangeDisplay
    local dir = nil

    if rangeKind == Enums.DamageRangeKind.DR_Kind_Region then
        isNeedShowRangeEffect = true
    elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
        isNeedShowRangeEffect = true
        dir = self.dir
    end

    if isNeedShowRangeEffect then
        self:showTargetedEffect(isVisible, rangeDisplay, dir)
    else
        self:showTargetedEffect(false, rangeDisplay, dir)
    end
end

function Actor:prepareTeamMark()
    -- if self._teamMarkNode == nil then
    --     self._teamMarkNode = cc.CSLoader:createNode(Res.BattleTeamMark,false,true)
    --     self:addChild(self._teamMarkNode)
    -- end
end

function Actor:setCurrentPlayerTargetFlag(isCurrentPlayerTarget)
    local isChanged = self.isCurrentPlayerTarget ~= isCurrentPlayerTarget
    self.isCurrentPlayerTarget = isCurrentPlayerTarget
    if self._playerNode then
        self._playerNode:setCurrentPlayerTargetFlag(isCurrentPlayerTarget)
    end
    if isChanged then
        self:refreshSelectEffect()
    end
end

function Actor:isOurTeam()
	if self.actorType == Enum_BattleActorType_self or self.actorType == Enum_BattleActorType_teammate then
		return true
	end
	return false
end

function Actor:getIsCurrentPlayerTarget()
    return self.isCurrentPlayerTarget
end

function Actor:getIsTimeMonster()
    return self.isTimeMonster
end

function Actor:setSoulCount(num)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setSoulCount(num)
    end
end

function Actor:playSoulChangeEffect(old, new)
    self:prepareStatusBar()
    if self._statusBar then
        if old < new then
            self._statusBar:playSoulGetEffect(new)
        else
            self._statusBar:playSoulLoseEffect(new)
        end
    end
end

function Actor:getCanRevive()
    --print("==============getCanRevive:",self.canRevive)
    return self.canRevive
end

function Actor:isFakeUnit()
    return self.isFakeNpc
end

function Actor:prepareStatusBar()
    if self.buildingType ~= Enums.buildingType.blood then
        if self._statusBar == nil then
            local statusBar = PlayerStatusBar.create()
            self._statusBar = statusBar
            self.statebarLayer:addChild(statusBar.root)
            statusBar:setAnchorPoint(cc.p(0.5,0))
            statusBar:setSpecialHPMax(self:getSpecialHPMax())
            statusBar:setIsTimeMonster(self.isTimeMonster)

            self._armature:addAttachment(statusBar.root,"point",0,0)
        end
        if self._skillEvent == nil then
            local skillEvent = SkillEvent.new(cc.CSLoader:createNode(Res.Node_skillevent_1, false, true))
            self._skillEvent = skillEvent
            self.statebarLayer:addChild(skillEvent.root)
            skillEvent:bindEvent(self)
            self._statusBar:bindSkillEventNode(skillEvent)
        end
    end
end

function Actor:updateSkillEventNodePosition()
    if cc.isAlive(self._statusBar) then
        self._statusBar:updateSkillEventNodePosition()
    end
end

function Actor:setSelectSize(selectSize)
    self.selectSize = selectSize
end

function Actor:setSelectExcursion(selectExcursion)
    self.selectExcursion = selectExcursion
end

function Actor:setFloatTextVisible(visible)
    if self.floatEffectPlayer then
        self.floatEffectPlayer:setVisible(visible)
    end

    if self._skillNameLayout then
        self._skillNameLayout:setVisible(visible)
    end
end

function Actor:setIsEnemy(isEnemy)
    self.bIsEnemy = isEnemy
end

function Actor:isEnemy(isEnemy)
    return self.bIsEnemy
end

function Actor:isNeutral()
    return self.bIsNeutral
end

function Actor:isLeft()
    return not self:isEnemy() and not self:isNeutral()
end

function Actor:getBuildingType()
    return self.buildingType or 0
end

function Actor:getHideHead()
    return self.hideHead
end

function Actor:setHideHead(bHideHead)
    self.hideHead = bHideHead
end

function Actor:setLevelColorBySelfLevel(controllerLevel)
    if self.bIsEnemy then
        if self.mLevel < controllerLevel then
            self.levelColorIndex = Enums.LevelColorIndex.low
        elseif self.mLevel == controllerLevel then
            self.levelColorIndex = Enums.LevelColorIndex.equal
        elseif self.mLevel > controllerLevel then
            if self.mLevel <= controllerLevel + 10 then
                self.levelColorIndex = Enums.LevelColorIndex.high
            else
                self.levelColorIndex = Enums.LevelColorIndex.superHigh
            end
        end
    else
        self.levelColorIndex = Enums.LevelColorIndex.normal
    end
end

--点击目标的时候显示选择特效
function Actor:setSelected()
    self:showSelectMark(true)
end

--点击目标之后 隐藏选择特效
function Actor:setUnSelected()
    self:showSelectMark(false)
end

function Actor:setTitleName(s)
    if s then
        self.name = s
    end

    if self._statusBar then
        self._statusBar:setName(s)
    end
end

function Actor:setDeadCtrlStatusVisible(b)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.Dead, b)
    end
end

function Actor:setPvpCtrlStatusVisible(b)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.PVP, b)
    end
end

function Actor:setGameOverCtrlStatusVisible(b)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.GameOver, b)
    end
end

function Actor:setFakeUnitCtrlStatusVisible(b)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.FakeUnit, b)
    end
end

function Actor:setWolfCtrlStatusVisible(b)
    self:prepareStatusBar()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.Wolf, b)
    end
end

function Actor:getName()
    return self.name
end

function Actor:setClassIcon(file)
    if file then
        self.classIcon = file
        if self._playerNode then
            self._playerNode:setClassIcon(file)
        end
    end
end

function Actor:getClassIcon()
    return self.classIcon
end

function Actor:setHpProgress(hp,hpMax,autoHide)
    local f = hp*100/hpMax
    self.hpPercent = f/100
    self:prepareStatusBar()
    if cc.isAlive(self._playerNode) then
        self._playerNode:setHpProgress(f,hp)
    end

    if cc.isAlive(self._statusBar) then
        self._statusBar:setPercent(f)
    end
end

function Actor:shouldHideAllHpUI(flag)
    if self._playerNode then
        self._playerNode:shouldHideAllHpUI(flag)
    end
    if self._statusBar then
        self._statusBar:shouldHideAllHpUI(flag)
    end
end

function Actor:isAlive()
    return not self:isDead()
end

function Actor:setManaProgress(mana,manaMax)
end

function Actor:setTeamMarkId(markId)
    --头上标记
    self:prepareTeamMark()
    self.markId = markId
end

function Actor:getMarkId()
    return self.markId
end

function Actor:revive()
    self:setDeadCtrlStatusVisible(false)
    if self._statusBar then
        self._statusBar:resetVisibleAfterRevive()
    end
end

function Actor:setColor(c)
    self:getArmature():setColor(c)
end

function Actor:setEffectColor(color)
    if self._curColorValue ~= color then
        self._curColorValue = color
        if color then
            self:getArmature():setColor(color)
        else
            self:getArmature():setColor(display.COLOR_WHITE)
        end
    end
end

function Actor:playSkillNameEffect(name, isComboSkill)
    if self:isFakeUnit() then
        return
    end

    local skillNameLayout = self._skillNameLayout

    if not skillNameLayout then
        skillNameLayout= ccui.Layout:create()
        self._skillNameLayout = skillNameLayout
        self:addChild(skillNameLayout)
    end

    if name and string_len(name) > 0 then
        -- local effect = cc.CSLoader:createNode(Res.BattleSkillNameEffect,false,true)
        local effect = SkillNameFloatView.create()
        effect:play(self:isSelfTeam(),name,isComboSkill)

        skillNameLayout:addChild(effect, 2)
        local _ ,headPosY = self:getHeadLocalPos()
        effect:setPosition(0,headPosY+100)
    end
end

function Actor:showBufffDisplayDesc(desc, displaySort)
    if self:isFakeUnit() then
        return
    end

    local skillNameLayout = self._skillNameLayout

    if not skillNameLayout then
        skillNameLayout= ccui.Layout:create()
        self:addChild(skillNameLayout)
        self._skillNameLayout = skillNameLayout
    end

    if desc then
        local effect = nil
        local textView = nil
        if displaySort == 1 then
            effect =  BuffNameFloatView.create()
        else
            effect = DebuffNameFloatView.create()
        end

        if effect then
            effect:play(self:isSelfTeam(),desc)
            skillNameLayout:addChild(effect, 1)
            local _,headPosY = self:getHeadLocalPos()
            effect:setPosition(0,headPosY+100)
        end
    end
end

function Actor:removeChantEffectEmitters()
    for _,v in pairs(self.chantEffectEmitters) do
        if v then
            v:remove()
        end
    end
    self.chantEffectEmitters={}
end

function Actor:cancelPlayingSkills()
    self.guideBar = nil

    -- for _,v in pairs(self.chantEffectEmitters) do
    --     if v then
    --         v:remove()
    --     end
    -- end
    -- self.chantEffectEmitters={}
    self:removeChantEffectEmitters()

    for _,v in pairs(self.effectEmitters) do
        v:remove()
    end
    self.effectEmitters={}
    self.sfxList={}

    local armature = self:getArmature()
    armature:stopAllActions()

    self.skillScaleStatus = Enums.SkillScaleStatus.noScale
    self:refreshActorScale()
end

function Actor:pushDamageFloatEffect(damage,isCritical, isBlocked, isTargetSelfTeam, isLimited)
    if self:isFakeUnit() then
        return
    end

    local effNode = DamageFloatView.create()
    effNode:play(damage, isCritical, isBlocked, isTargetSelfTeam, isLimited)
    self:pushFloatEff(effNode)
end

function Actor:pushInterrupedFloatEffect(isSelfTeam)
    if self:isFakeUnit() then
        return
    end

    local effNode = InterrupedFloatView.create()
    effNode:play(isSelfTeam)
    self:pushFloatEff(effNode)
end

function Actor:pushMissFloatEffect(isSelfTeam)
    if self:isFakeUnit() then
        return
    end

    local effNode = MissFloatView.create()
    effNode:play(isSelfTeam)
    self:pushFloatEff(effNode)
end

function Actor:pushAbsorbFloatEffect(isSelfTeam)
    if self:isFakeUnit() then
        return
    end

    local effNode = AbsorbFloatView.create()
    effNode:play(isSelfTeam)
    self:pushFloatEff(effNode)
end

function Actor:pushImmunityFloatEffect(isSelfTeam,str)
    if self:isFakeUnit() then
        return
    end

    local effNode = ImmunityFloatView.create()
    effNode:play(isSelfTeam, str)
    self:pushFloatEff(effNode)
end


function Actor:pushFloatEff(effNode)
    local posX,posY = CCNode_toLocalPosition(self:getParent(),self:getHeadPos())
    effNode:setPosition(posX,posY)

    self.floatEffectPlayer:push(effNode)
end

function Actor:onEffectDestroyed(event)
    local emitter = event.target
    self.effectEmitters[emitter.id]=nil
end

function Actor:onCatchSuccess()
    -- 捕捉宠物成功 todo
    self:playSkillNameEffect(L("lua_code_text_474"))
end

function Actor:onCatchInterrupt()
    -- 捕捉中断 todo
    self:playSkillNameEffect(L("lua_code_text_72"))
end

function Actor:showFlashHurtEffect()
    local armature = self:getArmature()
    local curShaderName = self:getCurShaderName()
    if curShaderName ~= "FlashHurt" then
        self:setNextShaderName(curShaderName)
        self:applyShader("FlashHurt")
        local actions = {
            cc.DelayTime:create(0.1),
            cc.CallFunc:create(function()
                local nextShaderName = self:getNextShaderName()
                self:applyShader(nextShaderName, true)
                self:setNextShaderName(nil)
            end)
        }
        self:runAction(cc.Sequence:create(actions))
    end
end

--Actor armature设置shader 必须调用Actor的方法，不能直接调用armature的方法
function Actor:applyShader(name, isForce)
    if (not isForce) and self._curShaderName == "FlashHurt" then
        self:setNextShaderName(name)
        return
    end
    self._curShaderName = name
    if cc.isAlive(self._armature) then
        self._armature:applyShaderWithName(name)
    end
end

function Actor:getCurShaderName()
    return self._curShaderName
end

function Actor:setNextShaderName(name)
    self._nextShaderName = name
end

function Actor:getNextShaderName()
    return self._nextShaderName
end

-----------------------------------effect --------------------------
function Actor:addEffectView(effecView)
    table.insert(self.effectsFollowDir, effecView)
    local function callback()
        local isnull = tolua.isnull(self)
        if (not isnull) and self.effectsFollowDir then
            for k,v in pairs(self.effectsFollowDir) do
                if effecView == v then
                    self.effectsFollowDir[k] = nil
                    break
                end
            end
        end
    end
    effecView:setParentRemoveCallBack(callback)
end


----------------------------------buff---------------------

function Actor:addBuffView(buffView, front)
    local index = self.buffIndex
    self.buffDict[index] = buffView
    -- table.insert(self.buffDict, buffView)
    local zOrder = 0
    if front then
        zOrder = ZOrderList.DB + 1
    else
        zOrder = ZOrderList.DB - 1
    end
    self:addChild(buffView,zOrder)
    -- self:addChild(buffView)
    self.buffIndex = self.buffIndex + 1

    local function callback()
        -- table.remove(self.buffDict, index)
        local isnull = tolua.isnull(self)
        if (not isnull) and self.buffDict then
            self.buffDict[index] = nil
        end
    end
    buffView:setParentRemoveCallBack(callback)
end

function Actor:getMiniSkillView()
    if self._playerNode then
        return self._playerNode.skillView
    end
end

function Actor:setControlId(id)
    self.controlId = id
end

function Actor:getControlId()
    return self.controlId
end

function Actor:refreshBuffs(entity)
    if self:isDead() then
        if self._statusBar then
            self._statusBar:showBuff(false,nil)
        end
        return
    end

    local buffUpdateIndex = self.buffUpdateIndex + 1
    self.buffUpdateIndex = buffUpdateIndex


    local curBuffStatusId = 0
    local buffScaleCount = 1.0
    local buffIconDict = self.buffIconDict
    local count = Unit_getBuffsLen(entity)

    --print("========refreshBuffs :",#buffs)
    local id = 0
    local buff = nil
    self.coreBuff = nil
    for i=1,count do
        if id == 0 then
            buff = Unit_getFirstBuff(entity)
        else
            buff = Unit_getNextBuffById(entity, id)
        end

        id = Entity_getId(buff)

        local layerCount = Buff_layerCount(buff)
        local leftTime = Entity_lifeRemain(buff)
        local maxTime = Buff_totalTime(buff)
        local createTime = Buff_createdTime(buff)

        local buffIconInfo = buffIconDict[id]
        local buffCfg = BuffModel:getBuffCfg(buff)
        local itemId = buff:getItemID()
        if buffIconInfo == nil and itemId==0 then --新增buff
            if buffCfg then
                local icon = buffCfg.icon
                if icon and string_len(icon) > 0 then
                    buffIconDict[id] = {}
                    buffIconInfo = buffIconDict[id]

                    buffIconInfo.icon = icon
                    buffIconInfo.sEffect = buffCfg.sEffect
                    buffIconInfo.changeRes = buffCfg.changeRes
                    buffIconInfo.bShowCD = buffCfg.bShowCD
                    buffIconInfo.buffId = buffCfg.buffId
                    buffIconInfo.name = buffCfg.name
                    buffIconInfo.desc = buffCfg.desc
                    buffIconInfo.displaySort = buffCfg.displaySort
                    buffIconInfo.bCore = buffCfg.bCore
                    buffIconInfo.casterId = buff:casterId()
                    if buffIconInfo.bCore and buffIconInfo.casterId == self:getControlId() then
                        self.coreBuff = buffIconInfo
                    end
                end
            end
        end

        if buffCfg then
            local buffEffectConfig = buffCfg.buffEffectConfig
            if buffEffectConfig then
                local buffStatusId = buffEffectConfig:getChangeStatus()
                if buffStatusId > 0 then
                    -- table.insert(buffStatus, buffStatusId)
                    if curBuffStatusId == 0 then
                        curBuffStatusId = buffStatusId
                    else
                        local curPriority = EffectPriority[curBuffStatusId] or 100
                        local priority = EffectPriority[buffStatusId] or 100
                        if priority < curPriority then
                            --越低 优先级越高
                            curBuffStatusId = buffStatusId
                        end
                    end
                end

                if layerCount <= 0 then
                    layerCount = 1
                end
                local percentScale = (buffEffectConfig:getScaleSize() - 100) * layerCount + 100
                if percentScale < 10 then
                    --缩放保护
                    percentScale = 10
                end
                local buffScale = percentScale*0.01
                -- table.insert(buffScaleList, buffScale)
                buffScaleCount = buffScaleCount * buffScale
            end
        end


        if buffIconInfo then
            buffIconInfo.buffUpdateIndex = buffUpdateIndex
            buffIconInfo.layerCount = layerCount
            buffIconInfo.leftTime = leftTime
            buffIconInfo.maxTime = maxTime
            buffIconInfo.createTime = createTime
            if buffIconInfo.bCore and buffIconInfo.casterId == self:getControlId() then
                self.coreBuff = buffIconInfo
            end
        end
    end


    --清空这次update没有的buff
    for k,v in pairs(buffIconDict) do
        if v.buffUpdateIndex ~= buffUpdateIndex then
            buffIconDict[k] = nil
        end
    end

    local effectController = self.effectController
    if effectController then
        effectController:apply(curBuffStatusId)
    end

    local needScale = math_abs(buffScaleCount - self.currentBuffScale) > 0.1
    if needScale then
        self.currentBuffScale = buffScaleCount
        self:refreshActorScale(true, nil)
    end

    if self.coreBuff then
        if self._statusBar then
            self._statusBar:showBuff(true,self.coreBuff)
        end
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_COREBONUS,self.id,true)
    else
        if self._statusBar then
            self._statusBar:showBuff(false,nil)
        end
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_COREBONUS,self.id,false)
    end
end

function Actor:getBuffIconDict()
    return self.buffIconDict
end

function Actor:isVisible()
    return self._armature:isVisible()
end

---------------------------------buff-end--------------------

function Actor:isSheep()
    if self.sheepArmature then
        return self.sheepArmature:isVisible()
    end
    return false
end

function Actor:turnSheep(b,changeRes)
    local Icon_Path = nil
    if b then
        if not self.sheepArmature then
            local resCfg =  string.split(changeRes, "/" )
            local armatureName = resCfg[2]
            local armatureNamePath = "armatures/characters/"..resCfg[1]
            Icon_Path = "art/npc_icon/"..resCfg[1]..".png"
            local sheepArmature = Armature.create({path=armatureNamePath,armatureName=armatureName,animationName="",skeletonName=armatureName})
            --sheepArmature:setScaleX(self:getArmature():getScaleX())
            --sheepArmature:setScaleY(self:getArmature():getScaleY())

            sheepArmature:setScaleX(math_abs(sheepArmature:getScaleX())*-self.dir)
            -- sheepArmature:setScaleX(math.abs(self.curScaleX)*-self.dir)
            self:addChild(sheepArmature,ZOrderList.DB)
            sheepArmature:play()
            self.sheepArmature = sheepArmature
        end

        self.sheepArmature:setVisible(true)
        self.originArmature:setVisible(false)
        self._armature = self.sheepArmature
    else
        if self.sheepArmature then
            self.sheepArmature:setVisible(false)
            self.originArmature:setVisible(true)
            self._armature = self.originArmature
        end
    end

    if b and Icon_Path then
        self:setCurrentIcon(Icon_Path)
    else
        if self.iconPath then
            self:setCurrentIcon(self.iconPath)
        end
    end
    self:dispatchEvent(Actor.Event_onIconChanged,self,self:getCurrentIcon())
    --修正变羊恢复后朝向错误
    self:updateDir()
end

function Actor:updateBuffStatus(status)
    if self.effectController then
        self.effectController:apply(status)
    end
end

function Actor:displayBubble(text,duration)
    if self:isDead() then
        --如果死亡 则不显示对话
        return
    end

    if not self.bubbleRoot then
        self.bubbleRoot = cc.Node:create()
        self.bubbleLayer:addChild(self.bubbleRoot)
    end

    app:sendMsg("IMModel", "addSystemMsg", self:getName()..": "..text, nil, true)

    --替换掉之前的对话
    self.bubbleRoot:removeAllChildren()
    local BubbleController = app:getClass("BubbleController")
    local bubble = BubbleController.new()
    self.bubbleRoot:addChild(bubble)
    local headPosX,headPosY = self.bubbleRoot:toLocalPosition(self:getHeadPos())
    bubble:setPosition(headPosX,headPosY)
    bubble:setContent(text)
    bubble:runAnimation()
    local action = cc.Sequence:create(cc.DelayTime:create(tonumber(duration)),cc.RemoveSelf:create())
    bubble:runAction(action)
end

function Actor:appendBubbleTask(task)
    -- table.insert(self.bubbleSequnce,task)
    if not self.bubbleSequnce then
        self.bubbleSequnce = {}
    end

    if not self.bubbleRoot then
        self.bubbleRoot = cc.Node:create()
        self.bubbleLayer:addChild(self.bubbleRoot)
        self._armature:addAttachment(self.bubbleRoot,"point",0,0)
    end

    self.bubbleSequnce[1] = task
end

--playernode
function Actor:setPlayerNode(node)
    self._playerNode = node
end

function Actor:getPlayerNode()
    return self._playerNode
end

function Actor:setFaceIcon(iconPath)
    self.iconPath = iconPath
    self:setCurrentIcon(iconPath)
end

function Actor:setCurrentIcon(iconPath)
    self.currentIconPath = iconPath
    if self._playerNode then
        self._playerNode:setIcon(iconPath)
    end
end

function Actor:getCurrentIcon()
    return self.currentIconPath
end

function Actor:setActorType(type, isPartner)
    self.actorType = type
     if self._statusBar then
       self._statusBar:setEnemy(self.actorType)
    end

    if self._playerNode then
        self._playerNode:setPlayerType(type)
        self._playerNode:setIsPartner(isPartner)
    end

    if self.actorType ~= Enum_BattleActorType_self then
        self:setVolume(Constant.BattleOtherSfxVolume)
        if self._playerNode then
            self._playerNode:setIsSelf(false)
        end
    else
        --如果是自己,沟边效果
        if self._playerNode then
            self._playerNode:setIsSelf(true)
        end
        self:displayOutlineEffect(true,1)
    end


    self:refreshArmatureAutoSound()
end


function Actor:setVolume(volume)
    self._volume = volume
    if self._armature then
        self._armature:setVolume(self._volume)
    end
end

function Actor:getVolume()
    return self._volume
end

function Actor:isSelfTeam()
    if self.actorType == Enum_BattleActorType_teammate or self.actorType == Enum_BattleActorType_self then
        return true
    end
    return false
end

function Actor:isSelf()
    if self.actorType == Enum_BattleActorType_self then
        return true
    end
    return false
end

function Actor:isCanPlayShake()
    --keep shake 和 notarget shake
    return self.actorType ~= Enum_BattleActorType_teammate
end

function Actor:setIsShowMana(isShowMana)
    self.isShowMana = isShowMana
end

function Actor:getIsShowMana()
    return self.isShowMana
end

function Actor:getActorType()
    return self.actorType
end

function Actor:setType(type)
    self.type = type

    if self._playerNode then
        self._playerNode:setType(type)
        self._playerNode:setFlip()
    end
end

function Actor:getFloatTextPosXIndex()
    self:stopActionByTag(Enums.CommonActionTag.FloatText)

    local posX = self.floatTextPosXIndex -- -1 0 1
    local index = math.random(1,100)
    if posX then
        --有位置
        index = math.mod(posX + math.mod(index,2) + 1,3) - 1
    else
        --没有位置,从中间开始
        index = 0
    end

    self.floatTextPosXIndex = index

    local actions = {}
    actions[1] = cc.DelayTime:create(0.5)
    actions[2] = cc.CallFunc:create(function() self.floatTextPosXIndex = nil end)

    local action = cc.Sequence:create(actions)
    action:setTag(Enums.CommonActionTag.FloatText)
    self:runAction(action)

    return self.floatTextPosXIndex
end

-- function Actor:addBuffScale(buffuid,scale)
--     if buffuid and scale then
--         self.buffScaleList[buffuid] = scale
--     end
--     self:refreshActorScale()
-- end

function Actor:getBuffScale(buffScaleList)
    local scale = 1.0
    for k,v in pairs(buffScaleList) do
        if v then
            scale = scale*v
        end
    end
    return scale
end

function Actor:getInLayerIndex()
    return self.inLayerIndex
end

function Actor:changeToBackLayer()
    self.inLayerIndex = Enums.BattleActorLayer.back
    -- self.isInFrontLayer = false
    self:setScaleInLayer(Constant.BattleBackLayerEntityScale)
    self:setPositionY(Constant.BattleBackLayerEntityPosY)
    if self._statusBar and cc.isAlive(self._statusBar.root) then
        self._statusBar.root:setLocalZOrder(0)
    end
end

function Actor:changeToFrontLayer()
    -- self.isInFrontLayer = true
    self.inLayerIndex = Enums.BattleActorLayer.front
    self:setScaleInLayer(1.0)
    self:setPositionY(0)
    if self._statusBar and cc.isAlive(self._statusBar.root) then
        self._statusBar.root:setLocalZOrder(TOP_STATUSBAR_ZORDER)
    end
end

function Actor:changeToSpecialLayer()
    -- self.isInFrontLayer = true
    self.inLayerIndex = Enums.BattleActorLayer.special
    self:setScaleInLayer(1.0)
    self:setPositionY(0)
end

function Actor:setScaleInLayer(s)
    if math_abs(s-self.layerScale)>0.01 then
        self.layerScale = s
        local armature = self.originArmature --大小缩放只对原型起作用， 对羊无效
        local action = armature:getActionByTag(Enum_CommonActionTag_BattleArmatureBuffScale)
        if action then
            --如果有action
            armature:stopActionByTag(Enum_CommonActionTag_BattleArmatureBuffScale)
        end
        self:refreshActorScale(false)
    end
end

function Actor:refreshActorScale(isUseAction, oldSkillScaleStatus)
    local  skillScaleStatus = self.skillScaleStatus
    if skillScaleStatus == Enum_SkillScaleStatus_noScale then
        local currentBuffScale = self.currentBuffScale
        local layerScale = self.layerScale

        local scaleTo = currentBuffScale*layerScale

        local armature = self.originArmature --大小缩放只对原型起作用， 对羊无效

        if isUseAction then
            --如果有缩放action,则不做缩放
            if armature:getActionByTag(Enum_CommonActionTag_BattleArmatureBuffScale) == nil then
                local scaleX , scaleY = self:getFinalScale(scaleTo)
                local action = cc.ScaleTo:create(0.1,scaleX,scaleY)
                action:setTag(Enum_CommonActionTag_BattleArmatureBuffScale)
                armature:runAction(action)
            end
        else
            self:setScale(scaleTo)
        end
    elseif skillScaleStatus == Enum_SkillScaleStatus_castScale then
        --正在做技能放大
        --nothing todo
    elseif skillScaleStatus == Enum_SkillScaleStatus_scaleToNormal then
        --正在做技能正常缩放
        --nothing todo
    end
end

function Actor:showPlayerTips()
    if self._playerNode then
        self._playerNode:showTips({name = self:getName(), level = self.mLevel, className = self.mClassName,buffList = self.buffIconDict})
    end

end

function Actor:hidePlayerTips()
    if self._playerNode then
        self._playerNode:hideTips()
    end
end

function Actor:containWorldPoint(x,y)
    return self._armature:containWorldPoint(x,y)
end

function Actor:getUnitModelId()
    return self.unitModelId
end

function Actor:setShouldRemove(b)
    self.mIsShouldRemove = b
end

function Actor:isShouldRemove()
    return self.mIsShouldRemove
end

function Actor:refreshHpBarVisible()
end

function Actor:filterBuffStatus(buffStatus)
    local values = table.values(buffStatus)
    values = table.unique(values)

    local result = Enums.BuffEffects.None
    if #values >1 then
        table.sort(values,function(l,r)
            local lnum = EffectPriority[l] or 100
            local rnum = EffectPriority[r] or 100
            return lnum < rnum
        end)
        result = values[1]
    elseif #values==1 then
        result = values[1]
    end
    assert(type(result)=="number","must be number but is "..type(result))
    return result
end

-------------------聊天-----------------------------
function Actor:getUid()
    return self.uid
end

function Actor:isMVP()
    return self.bMVP
end

function Actor:setMVP(bMVP)
    self.bMVP = bMVP
end

function Actor:getIMBubble()
    return self.mIMBubble
end

function Actor:setIMBubble(render)
    self.mIMBubble = render
    self.bubbleLayer:addChild(self.mIMBubble)
    self.mIMBubble:setVisible(false)
    self._armature:addAttachment(self.mIMBubble,"point",0,0)
end

function Actor:showIMBubble(content, showTime, overCall)
    local armature = self._armature
    if not armature then return end
    if not self.mIMBubble then return end
    showTime = tonumber(showTime or 5)
    self.mIMBubble:setVisible(true)
    self.mIMBubble:stopAction(self.mIMAct)

    local x,y = self:getHeadPos()
    print("Actor:showIMBubble")
    self.mIMBubble:setContent(content)
    self.mIMBubble:play()

    local function callback()
        self:hideIMBubble()
        executeFunc(overCall)
    end
    local action = cc.Sequence:create(cc.DelayTime:create(showTime), cc.CallFunc:create(callback))
    self.mIMAct = self.mIMBubble:runAction(action)
end

function Actor:hideIMBubble()
    if not self.mIMBubble then return end
    self.mIMBubble:setVisible(false)
    self.mIMAct = nil
end

function Actor:show()
    CCNode_setVisible(self, true)
end

function Actor:hide()
    CCNode_setVisible(self, false)
end

function Actor:enterStealth()
    if self.flagInStealth then
        return false
    end
    self.flagInStealth = true
    self:hide()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.Stealth, true)
    end
    if not cc.isDead(self._playerNode) then
        self._playerNode:setSortWeight(0)
        CCNode_setVisible(self._playerNode, false)
    end

    return true
end

function Actor:leaveStealth()
    if not self.flagInStealth then
        return false
    end
    self.flagInStealth = false
    self:show()
    if self._statusBar then
        self._statusBar:setCtrlVisible(Enums.BattleStatusBarVisibleCtrlPriority.Stealth, false)
    end
    if not cc.isDead(self._playerNode) then
        self._playerNode:setSortWeight(nil)
        CCNode_setVisible(self._playerNode, true)
    end

    return true
end

function Actor:setOpacity(opacity)
    Armature_setFBOOpacity(self._armature,opacity)
end

local Actor_idle = Actor.idle
local Actor_isDead = Actor.isDead

function Actor:checkDeathOrReborn(isDead)
    if self.lastDeadState == "dead" and not isDead then
        if self._armature:isPlaying("dead") then
            self._armature:clearCompletedCallBack()
        end

        local playerNode = self._playerNode
        if playerNode then
            playerNode:stopActionByTag(Enums.CommonActionTag.BattleActorReborn)
        end
        self._armature:stopActionByTag(Enums.CommonActionTag.BattleActorReborn)
        self:stopActionByTag(Enums.CommonActionTag.BattleActorDeadAnimationEnd)
        --reborn
        local act1 = cca.seq({cca.fadeIn(0.0),cca.callFunc(function()
        CCNode_setVisible(self._armature, true)
        end)})
        self._armature:runAction(act1)

        if playerNode and not playerNode:getParent() then
            playerNode:setSortWeight(1)
            CCNode_setVisible(playerNode, true)
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, playerNode:isLeftSide(),{playerNode})
            playerNode:release()
        end
    end

    if isDead then
        self.lastDeadState = "dead"
    else
        self.lastDeadState = "alive"
    end
end

local Actor_checkDeathOrReborn = Actor.checkDeathOrReborn

function Actor:tick(dt)
    self._pointPosDirty = true

    local isDead = Actor_isDead(self)
    local armature = self._armature
    if (not isDead) and armature and (not Armature_isPlaying(armature)) then
        Actor_idle(self)
    end

    local bubbleSeq = self.bubbleSequnce
    if bubbleSeq and self.bubbleRoot and CCNode_getChildrenCount(self.bubbleRoot)==0 and #bubbleSeq>0 then
        local task = bubbleSeq[1]
        self:displayBubble(task.text,task.duration)
        table.remove(self.bubbleSequnce,1)
    end

    local statusBar = self._statusBar
    if statusBar then
        statusBar:setSelect(self.isCurrentPlayerTarget)
        local actorType = self.actorType
        if actorType == Enum_BattleActorType_teammate then
            statusBar:setEnemy(actorType)
        end
        if isDead then
            statusBar:setFlag(false)
        else
            statusBar:setFlag(self:getMarkId() == 1)
        end
    end

    -- display bounding box
    Actor_checkDeathOrReborn(self,isDead)
end
-----------------------------------------------------------------

return Actor
